mirror of
https://github.com/Ai-Thinker-Open/Ai-Thinker-Open_RTL8710BX_ALIOS_SDK.git
synced 2025-07-31 19:31:05 +00:00
rel_1.6.0 init
This commit is contained in:
commit
27b3e2883d
19359 changed files with 8093121 additions and 0 deletions
2241
Living_SDK/kernel/protocols/bluetooth/host/att.c
Normal file
2241
Living_SDK/kernel/protocols/bluetooth/host/att.c
Normal file
File diff suppressed because it is too large
Load diff
251
Living_SDK/kernel/protocols/bluetooth/host/att_internal.h
Normal file
251
Living_SDK/kernel/protocols/bluetooth/host/att_internal.h
Normal file
|
|
@ -0,0 +1,251 @@
|
|||
/* att_internal.h - Attribute protocol handling */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2015-2016 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#define BT_ATT_DEFAULT_LE_MTU 23
|
||||
|
||||
#if BT_L2CAP_RX_MTU < CONFIG_BT_L2CAP_TX_MTU
|
||||
#define BT_ATT_MTU BT_L2CAP_RX_MTU
|
||||
#else
|
||||
#define BT_ATT_MTU CONFIG_BT_L2CAP_TX_MTU
|
||||
#endif
|
||||
|
||||
struct bt_att_hdr {
|
||||
u8_t code;
|
||||
} __packed;
|
||||
|
||||
#define BT_ATT_OP_ERROR_RSP 0x01
|
||||
struct bt_att_error_rsp {
|
||||
u8_t request;
|
||||
u16_t handle;
|
||||
u8_t error;
|
||||
} __packed;
|
||||
|
||||
#define BT_ATT_OP_MTU_REQ 0x02
|
||||
struct bt_att_exchange_mtu_req {
|
||||
u16_t mtu;
|
||||
} __packed;
|
||||
|
||||
#define BT_ATT_OP_MTU_RSP 0x03
|
||||
struct bt_att_exchange_mtu_rsp {
|
||||
u16_t mtu;
|
||||
} __packed;
|
||||
|
||||
/* Find Information Request */
|
||||
#define BT_ATT_OP_FIND_INFO_REQ 0x04
|
||||
struct bt_att_find_info_req {
|
||||
u16_t start_handle;
|
||||
u16_t end_handle;
|
||||
} __packed;
|
||||
|
||||
/* Format field values for BT_ATT_OP_FIND_INFO_RSP */
|
||||
#define BT_ATT_INFO_16 0x01
|
||||
#define BT_ATT_INFO_128 0x02
|
||||
|
||||
struct bt_att_info_16 {
|
||||
u16_t handle;
|
||||
u16_t uuid;
|
||||
} __packed;
|
||||
|
||||
struct bt_att_info_128 {
|
||||
u16_t handle;
|
||||
u8_t uuid[16];
|
||||
} __packed;
|
||||
|
||||
/* Find Information Response */
|
||||
#define BT_ATT_OP_FIND_INFO_RSP 0x05
|
||||
struct bt_att_find_info_rsp {
|
||||
u8_t format;
|
||||
u8_t info[0];
|
||||
} __packed;
|
||||
|
||||
/* Find By Type Value Request */
|
||||
#define BT_ATT_OP_FIND_TYPE_REQ 0x06
|
||||
struct bt_att_find_type_req {
|
||||
u16_t start_handle;
|
||||
u16_t end_handle;
|
||||
u16_t type;
|
||||
u8_t value[0];
|
||||
} __packed;
|
||||
|
||||
struct bt_att_handle_group {
|
||||
u16_t start_handle;
|
||||
u16_t end_handle;
|
||||
} __packed;
|
||||
|
||||
/* Find By Type Value Response */
|
||||
#define BT_ATT_OP_FIND_TYPE_RSP 0x07
|
||||
struct bt_att_find_type_rsp {
|
||||
struct bt_att_handle_group list[0];
|
||||
} __packed;
|
||||
|
||||
/* Read By Type Request */
|
||||
#define BT_ATT_OP_READ_TYPE_REQ 0x08
|
||||
struct bt_att_read_type_req {
|
||||
u16_t start_handle;
|
||||
u16_t end_handle;
|
||||
u8_t uuid[0];
|
||||
} __packed;
|
||||
|
||||
struct bt_att_data {
|
||||
u16_t handle;
|
||||
u8_t value[0];
|
||||
} __packed;
|
||||
|
||||
/* Read By Type Response */
|
||||
#define BT_ATT_OP_READ_TYPE_RSP 0x09
|
||||
struct bt_att_read_type_rsp {
|
||||
u8_t len;
|
||||
struct bt_att_data data[0];
|
||||
} __packed;
|
||||
|
||||
/* Read Request */
|
||||
#define BT_ATT_OP_READ_REQ 0x0a
|
||||
struct bt_att_read_req {
|
||||
u16_t handle;
|
||||
} __packed;
|
||||
|
||||
/* Read Response */
|
||||
#define BT_ATT_OP_READ_RSP 0x0b
|
||||
struct bt_att_read_rsp {
|
||||
u8_t value[0];
|
||||
} __packed;
|
||||
|
||||
/* Read Blob Request */
|
||||
#define BT_ATT_OP_READ_BLOB_REQ 0x0c
|
||||
struct bt_att_read_blob_req {
|
||||
u16_t handle;
|
||||
u16_t offset;
|
||||
} __packed;
|
||||
|
||||
/* Read Blob Response */
|
||||
#define BT_ATT_OP_READ_BLOB_RSP 0x0d
|
||||
struct bt_att_read_blob_rsp {
|
||||
u8_t value[0];
|
||||
} __packed;
|
||||
|
||||
/* Read Multiple Request */
|
||||
#define BT_ATT_READ_MULT_MIN_LEN_REQ 0x04
|
||||
|
||||
#define BT_ATT_OP_READ_MULT_REQ 0x0e
|
||||
struct bt_att_read_mult_req {
|
||||
u16_t handles[0];
|
||||
} __packed;
|
||||
|
||||
/* Read Multiple Respose */
|
||||
#define BT_ATT_OP_READ_MULT_RSP 0x0f
|
||||
struct bt_att_read_mult_rsp {
|
||||
u8_t value[0];
|
||||
} __packed;
|
||||
|
||||
/* Read by Group Type Request */
|
||||
#define BT_ATT_OP_READ_GROUP_REQ 0x10
|
||||
struct bt_att_read_group_req {
|
||||
u16_t start_handle;
|
||||
u16_t end_handle;
|
||||
u8_t uuid[0];
|
||||
} __packed;
|
||||
|
||||
struct bt_att_group_data {
|
||||
u16_t start_handle;
|
||||
u16_t end_handle;
|
||||
u8_t value[0];
|
||||
} __packed;
|
||||
|
||||
/* Read by Group Type Response */
|
||||
#define BT_ATT_OP_READ_GROUP_RSP 0x11
|
||||
struct bt_att_read_group_rsp {
|
||||
u8_t len;
|
||||
struct bt_att_group_data data[0];
|
||||
} __packed;
|
||||
|
||||
/* Write Request */
|
||||
#define BT_ATT_OP_WRITE_REQ 0x12
|
||||
struct bt_att_write_req {
|
||||
u16_t handle;
|
||||
u8_t value[0];
|
||||
} __packed;
|
||||
|
||||
/* Write Response */
|
||||
#define BT_ATT_OP_WRITE_RSP 0x13
|
||||
|
||||
/* Prepare Write Request */
|
||||
#define BT_ATT_OP_PREPARE_WRITE_REQ 0x16
|
||||
struct bt_att_prepare_write_req {
|
||||
u16_t handle;
|
||||
u16_t offset;
|
||||
u8_t value[0];
|
||||
} __packed;
|
||||
|
||||
/* Prepare Write Respond */
|
||||
#define BT_ATT_OP_PREPARE_WRITE_RSP 0x17
|
||||
struct bt_att_prepare_write_rsp {
|
||||
u16_t handle;
|
||||
u16_t offset;
|
||||
u8_t value[0];
|
||||
} __packed;
|
||||
|
||||
/* Execute Write Request */
|
||||
#define BT_ATT_FLAG_CANCEL 0x00
|
||||
#define BT_ATT_FLAG_EXEC 0x01
|
||||
|
||||
#define BT_ATT_OP_EXEC_WRITE_REQ 0x18
|
||||
struct bt_att_exec_write_req {
|
||||
u8_t flags;
|
||||
} __packed;
|
||||
|
||||
/* Execute Write Response */
|
||||
#define BT_ATT_OP_EXEC_WRITE_RSP 0x19
|
||||
|
||||
/* Handle Value Notification */
|
||||
#define BT_ATT_OP_NOTIFY 0x1b
|
||||
struct bt_att_notify {
|
||||
u16_t handle;
|
||||
u8_t value[0];
|
||||
} __packed;
|
||||
|
||||
/* Handle Value Indication */
|
||||
#define BT_ATT_OP_INDICATE 0x1d
|
||||
struct bt_att_indicate {
|
||||
u16_t handle;
|
||||
u8_t value[0];
|
||||
} __packed;
|
||||
|
||||
/* Handle Value Confirm */
|
||||
#define BT_ATT_OP_CONFIRM 0x1e
|
||||
|
||||
struct bt_att_signature {
|
||||
u8_t value[12];
|
||||
} __packed;
|
||||
|
||||
/* Write Command */
|
||||
#define BT_ATT_OP_WRITE_CMD 0x52
|
||||
struct bt_att_write_cmd {
|
||||
u16_t handle;
|
||||
u8_t value[0];
|
||||
} __packed;
|
||||
|
||||
/* Signed Write Command */
|
||||
#define BT_ATT_OP_SIGNED_WRITE_CMD 0xd2
|
||||
struct bt_att_signed_write_cmd {
|
||||
u16_t handle;
|
||||
u8_t value[0];
|
||||
} __packed;
|
||||
|
||||
void bt_att_init(void);
|
||||
u16_t bt_att_get_mtu(struct bt_conn *conn);
|
||||
struct net_buf *bt_att_create_pdu(struct bt_conn *conn, u8_t op,
|
||||
size_t len);
|
||||
|
||||
/* Send ATT PDU over a connection */
|
||||
int bt_att_send(struct bt_conn *conn, struct net_buf *buf);
|
||||
|
||||
/* Send ATT Request over a connection */
|
||||
int bt_att_req_send(struct bt_conn *conn, struct bt_att_req *req);
|
||||
|
||||
/* Cancel ATT request */
|
||||
void bt_att_req_cancel(struct bt_conn *conn, struct bt_att_req *req);
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
zephyr_library()
|
||||
zephyr_library_link_libraries(subsys__bluetooth)
|
||||
|
||||
zephyr_library_sources_ifdef(CONFIG_BT_MESH
|
||||
main.c
|
||||
adv.c
|
||||
beacon.c
|
||||
net.c
|
||||
transport.c
|
||||
crypto.c
|
||||
access.c
|
||||
cfg_srv.c
|
||||
health_srv.c
|
||||
)
|
||||
|
||||
zephyr_library_sources_ifdef(CONFIG_BT_MESH_LOW_POWER lpn.c)
|
||||
|
||||
zephyr_library_sources_ifdef(CONFIG_BT_MESH_FRIEND friend.c)
|
||||
|
||||
zephyr_library_sources_ifdef(CONFIG_BT_MESH_PROV prov.c)
|
||||
|
||||
zephyr_library_sources_ifdef(CONFIG_BT_MESH_PROXY proxy.c)
|
||||
|
||||
zephyr_library_sources_ifdef(CONFIG_BT_MESH_CFG_CLI cfg_cli.c)
|
||||
|
||||
zephyr_library_sources_ifdef(CONFIG_BT_MESH_HEALTH_CLI health_cli.c)
|
||||
|
||||
zephyr_library_sources_ifdef(CONFIG_BT_MESH_SELF_TEST test.c)
|
||||
|
||||
zephyr_library_sources_ifdef(CONFIG_BT_MESH_SHELL shell.c)
|
||||
459
Living_SDK/kernel/protocols/bluetooth/host/bt_mesh/Kconfig
Normal file
459
Living_SDK/kernel/protocols/bluetooth/host/bt_mesh/Kconfig
Normal file
|
|
@ -0,0 +1,459 @@
|
|||
# Kconfig - Bluetooth Mesh configuration options
|
||||
|
||||
#
|
||||
# Copyright (c) 2017 Intel Corporation
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
menuconfig BT_MESH
|
||||
bool "Bluetooth Mesh support"
|
||||
select TINYCRYPT
|
||||
select TINYCRYPT_AES
|
||||
select TINYCRYPT_AES_CMAC
|
||||
help
|
||||
This option enables Bluetooth Mesh support. The specific
|
||||
features that are available may depend on other features
|
||||
that have been enabled in the stack, such as GATT support.
|
||||
|
||||
if BT_MESH
|
||||
|
||||
# Virtual option enabled whenever Generic Provisioning layer is needed
|
||||
config BT_MESH_PROV
|
||||
bool
|
||||
|
||||
config BT_MESH_PB_ADV
|
||||
bool "Provisioning support using the advertising bearer (PB-ADV)"
|
||||
select BT_MESH_PROV
|
||||
default y
|
||||
help
|
||||
Enable this option to allow the device to be provisioned over
|
||||
the advertising bearer.
|
||||
|
||||
if BT_CONN
|
||||
|
||||
# Virtual option enabled whenever any Proxy protocol is needed
|
||||
config BT_MESH_PROXY
|
||||
bool
|
||||
|
||||
config BT_MESH_PB_GATT
|
||||
bool "Provisioning support using GATT (PB-GATT)"
|
||||
select BT_MESH_PROXY
|
||||
select BT_MESH_PROV
|
||||
help
|
||||
Enable this option to allow the device to be provisioned over
|
||||
GATT.
|
||||
|
||||
config BT_MESH_GATT_PROXY
|
||||
bool "GATT Proxy Service"
|
||||
select BT_MESH_PROXY
|
||||
help
|
||||
This option enables support for the Mesh GATT Proxy Service,
|
||||
i.e. the ability to act as a proxy between a Mesh GATT Client
|
||||
and a Mesh network.
|
||||
|
||||
config BT_MESH_NODE_ID_TIMEOUT
|
||||
int "Node Identity advertising timeout"
|
||||
depends on BT_MESH_GATT_PROXY
|
||||
range 1 60
|
||||
default 60
|
||||
help
|
||||
This option determines for how long the local node advertises
|
||||
using Node Identity. The given value is in seconds. The
|
||||
specification limits this to 60 seconds, and implies that to
|
||||
be the appropriate value as well, so just leaving this as the
|
||||
default is the safest option.
|
||||
|
||||
if BT_MESH_PROXY
|
||||
|
||||
config BT_MESH_PROXY_FILTER_SIZE
|
||||
int "Maximum number of filter entries per Proxy Client"
|
||||
default 1
|
||||
default 3 if BT_MESH_GATT_PROXY
|
||||
range 1 32767
|
||||
help
|
||||
This option specifies how many Proxy Filter entries the local
|
||||
node supports.
|
||||
|
||||
endif # BT_MESH_PROXY
|
||||
|
||||
endif # BT_CONN
|
||||
|
||||
config BT_MESH_SELF_TEST
|
||||
bool "Perform self-tests"
|
||||
help
|
||||
This option adds extra self-tests which are run every time
|
||||
mesh networking is initialized.
|
||||
|
||||
config BT_MESH_IV_UPDATE_TEST
|
||||
bool "Test the IV Update Procedure"
|
||||
help
|
||||
This option removes the 96 hour limit of the IV Update
|
||||
Procedure and lets the state be changed at any time.
|
||||
|
||||
config BT_MESH_SUBNET_COUNT
|
||||
int "Maximum number of mesh subnets per network"
|
||||
default 1
|
||||
range 1 4096
|
||||
help
|
||||
This option specifies how many subnets a Mesh network can
|
||||
participate in at the same time.
|
||||
|
||||
config BT_MESH_APP_KEY_COUNT
|
||||
int "Maximum number of application keys per network"
|
||||
default 1
|
||||
range 1 4096
|
||||
help
|
||||
This option specifies how many application keys the device can
|
||||
store per network.
|
||||
|
||||
config BT_MESH_MODEL_KEY_COUNT
|
||||
int "Maximum number of application keys per model"
|
||||
default 1
|
||||
range 1 4096
|
||||
help
|
||||
This option specifies how many application keys each model can
|
||||
at most be bound to.
|
||||
|
||||
config BT_MESH_MODEL_GROUP_COUNT
|
||||
int "Maximum number of group address subscriptions per model"
|
||||
default 1
|
||||
range 1 4096
|
||||
help
|
||||
This option specifies how many group addresses each model can
|
||||
at most be subscribed to.
|
||||
|
||||
config BT_MESH_LABEL_COUNT
|
||||
int "Maximum number of Label UUIDs used for Virtual Addresses"
|
||||
default 1
|
||||
range 0 4096
|
||||
help
|
||||
This option specifies how many Label UUIDs can be stored.
|
||||
|
||||
config BT_MESH_CRPL
|
||||
int "Maximum capacity of the replay protection list"
|
||||
default 10
|
||||
range 2 65535
|
||||
help
|
||||
This options specifies the maximum capacity of the replay
|
||||
protection list. This option is similar to the network message
|
||||
cache size, but has a different purpose.
|
||||
|
||||
config BT_MESH_MSG_CACHE_SIZE
|
||||
int "Network message cache size"
|
||||
default 10
|
||||
range 2 65535
|
||||
help
|
||||
Number of messages that are cached for the network. This helps
|
||||
prevent unnecessary decryption operations and unnecessary
|
||||
relays. This option is similar to the replay protection list,
|
||||
but has a different purpose.
|
||||
|
||||
config BT_MESH_ADV_BUF_COUNT
|
||||
int "Number of advertising buffers"
|
||||
default 6
|
||||
range 6 256
|
||||
help
|
||||
Number of advertising buffers available. The transport layer
|
||||
reserves ADV_BUF_COUNT - 3 buffers for outgoing segments. The
|
||||
maximum outgoing SDU size is 12 times this number (out of which
|
||||
4 or 8 bytes is used for the Transport Layer MIC). For
|
||||
example, 5 segments means the maximum SDU size is 60 bytes,
|
||||
which leaves 56 bytes for application layer data using a
|
||||
4-byte MIC and 52 bytes using an 8-byte MIC.
|
||||
|
||||
config BT_MESH_TX_SEG_MSG_COUNT
|
||||
int "Maximum number of simultaneous outgoing segmented messages"
|
||||
default 1
|
||||
range 1 BT_MESH_ADV_BUF_COUNT
|
||||
help
|
||||
Maximum number of simultaneous outgoing multi-segment and/or
|
||||
reliable messages.
|
||||
|
||||
config BT_MESH_RX_SEG_MSG_COUNT
|
||||
int "Maximum number of simultaneous incoming segmented messages"
|
||||
default 1
|
||||
range 1 255
|
||||
help
|
||||
Maximum number of simultaneous incoming multi-segment and/or
|
||||
reliable messages.
|
||||
|
||||
config BT_MESH_RX_SDU_MAX
|
||||
int "Maximum incoming Upper Transport Access PDU length"
|
||||
default 384
|
||||
range 36 384
|
||||
help
|
||||
Maximum incoming Upper Transport Access PDU length. Leave this
|
||||
to the default value, unless you really need to optimize memory
|
||||
usage.
|
||||
|
||||
config BT_MESH_RELAY
|
||||
bool "Relay support"
|
||||
help
|
||||
Support for acting as a Mesh Relay Node.
|
||||
|
||||
config BT_MESH_LOW_POWER
|
||||
bool "Support for Low Power features"
|
||||
help
|
||||
Enable this option to be able to act as a Low Power Node.
|
||||
|
||||
if BT_MESH_LOW_POWER
|
||||
|
||||
config BT_MESH_LPN_ESTABLISHMENT
|
||||
bool "Perform Friendship establishment using low power"
|
||||
default y
|
||||
help
|
||||
Perform the Friendship establishment using low power, with
|
||||
the help of a reduced scan duty cycle. The downside of this
|
||||
is that the node may miss out on messages intended for it
|
||||
until it has successfully set up Friendship with a Friend
|
||||
node.
|
||||
|
||||
config BT_MESH_LPN_AUTO
|
||||
bool "Automatically start looking for Friend nodes once provisioned"
|
||||
default y
|
||||
help
|
||||
Automatically enable LPN functionality once provisioned and start
|
||||
looking for Friend nodes. If this option is disabled LPN mode
|
||||
needs to be manually enabled by calling bt_mesh_lpn_set(true).
|
||||
|
||||
config BT_MESH_LPN_AUTO_TIMEOUT
|
||||
int "Time from last received message before going to LPN mode"
|
||||
default 15
|
||||
range 0 3600
|
||||
depends on BT_MESH_LPN_AUTO
|
||||
help
|
||||
Time in seconds from the last received message, that the node
|
||||
will wait before starting to look for Friend nodes.
|
||||
|
||||
config BT_MESH_LPN_RETRY_TIMEOUT
|
||||
int "Retry timeout for Friend requests"
|
||||
default 8
|
||||
range 1 3600
|
||||
help
|
||||
Time in seconds between Friend Requests, if a previous Friend
|
||||
Request did not receive any acceptable Friend Offers.
|
||||
|
||||
config BT_MESH_LPN_RSSI_FACTOR
|
||||
int "RSSIFactor, used in the Friend Offer Delay calculation"
|
||||
range 0 3
|
||||
default 0
|
||||
help
|
||||
The contribution of the RSSI measured by the Friend node used
|
||||
in Friend Offer Delay calculations. 0 = 1, 1 = 1.5, 2 = 2, 3 = 2.5.
|
||||
|
||||
config BT_MESH_LPN_RECV_WIN_FACTOR
|
||||
int "ReceiveWindowFactor, used in the Friend Offer Delay calculation"
|
||||
range 0 3
|
||||
default 0
|
||||
help
|
||||
The contribution of the supported Receive Window used in
|
||||
Friend Offer Delay calculations. 0 = 1, 1 = 1.5, 2 = 2, 3 = 2.5.
|
||||
|
||||
config BT_MESH_LPN_MIN_QUEUE_SIZE
|
||||
int "Minimum size of acceptable friend queue (MinQueueSizeLog)"
|
||||
range 1 7
|
||||
default 1
|
||||
help
|
||||
The MinQueueSizeLog field is defined as log_2(N), where N is
|
||||
the minimum number of maximum size Lower Transport PDUs that
|
||||
the Friend node can store in its Friend Queue. As an example,
|
||||
MinQueueSizeLog value 1 gives N = 2, and value 7 gives N = 128.
|
||||
|
||||
config BT_MESH_LPN_RECV_DELAY
|
||||
int "Receive delay requested by the local node"
|
||||
range 10 255
|
||||
default 100
|
||||
help
|
||||
The ReceiveDelay is the time between the Low Power node
|
||||
sending a request and listening for a response. This delay
|
||||
allows the Friend node time to prepare the response. The value
|
||||
is in units of milliseconds.
|
||||
|
||||
config BT_MESH_LPN_POLL_TIMEOUT
|
||||
int "The value of the PollTimeout timer"
|
||||
range 10 244735
|
||||
default 300
|
||||
help
|
||||
PollTimeout timer is used to measure time between two
|
||||
consecutive requests sent by the Low Power node. If no
|
||||
requests are received by the Friend node before the
|
||||
PollTimeout timer expires, then the friendship is considered
|
||||
terminated. The value is in units of 100 milliseconds, so e.g.
|
||||
a value of 300 means 3 seconds.
|
||||
|
||||
config BT_MESH_LPN_INIT_POLL_TIMEOUT
|
||||
int "The starting value of the PollTimeout timer"
|
||||
range 10 BT_MESH_LPN_POLL_TIMEOUT
|
||||
default BT_MESH_LPN_POLL_TIMEOUT
|
||||
help
|
||||
The initial value of the PollTimeout timer when Friendship
|
||||
gets established for the first time. After this the timeout
|
||||
will gradually grow toward the actual PollTimeout, doubling
|
||||
in value for each iteration. The value is in units of 100
|
||||
milliseconds, so e.g. a value of 300 means 30 seconds.
|
||||
|
||||
config BT_MESH_LPN_SCAN_LATENCY
|
||||
int "Latency for enabling scanning"
|
||||
range 0 50
|
||||
default 10
|
||||
help
|
||||
Latency in milliseconds that it takes to enable scanning. This
|
||||
is in practice how much time in advance before the Receive Window
|
||||
that scanning is requested to be enabled.
|
||||
|
||||
config BT_MESH_LPN_GROUPS
|
||||
int "Number of groups the LPN can subscribe to"
|
||||
range 0 16384
|
||||
default 8
|
||||
help
|
||||
Maximum number of groups that the LPN can subscribe to.
|
||||
endif # BT_MESH_LOW_POWER
|
||||
|
||||
config BT_MESH_FRIEND
|
||||
bool "Support for acting as a Friend Node"
|
||||
help
|
||||
Enable this option to be able to act as a Friend Node.
|
||||
|
||||
if BT_MESH_FRIEND
|
||||
|
||||
config BT_MESH_FRIEND_RECV_WIN
|
||||
int "Friend Receive Window"
|
||||
range 1 255
|
||||
default 255
|
||||
help
|
||||
Receive Window in milliseconds supported by the Friend node.
|
||||
|
||||
config BT_MESH_FRIEND_QUEUE_SIZE
|
||||
int "Minimum number of buffers supported per Friend Queue"
|
||||
range 2 65536
|
||||
default 16
|
||||
help
|
||||
Minimum number of buffers available to be stored for each
|
||||
local Friend Queue.
|
||||
|
||||
config BT_MESH_FRIEND_SUB_LIST_SIZE
|
||||
int "Friend Subscription List Size"
|
||||
range 0 1023
|
||||
default 3
|
||||
help
|
||||
Size of the Subscription List that can be supported by a
|
||||
Friend node for a Low Power node.
|
||||
|
||||
config BT_MESH_FRIEND_LPN_COUNT
|
||||
int "Number of supported LPN nodes"
|
||||
range 1 1000
|
||||
default 2
|
||||
help
|
||||
Number of Low Power Nodes the Friend can have a Friendship
|
||||
with simultaneously.
|
||||
|
||||
config BT_MESH_FRIEND_SEG_RX
|
||||
int "Number of incomplete segment lists per LPN"
|
||||
range 1 1000
|
||||
default 1
|
||||
help
|
||||
Number of incomplete segment lists that we track for each LPN
|
||||
that we are Friends for. In other words, this determines how
|
||||
many elements we can simultaneously be receiving segmented
|
||||
messages from when the messages are going into the Friend queue.
|
||||
|
||||
endif # BT_MESH_FRIEND
|
||||
|
||||
config BT_MESH_CFG_CLI
|
||||
bool "Support for Configuration Client Model"
|
||||
help
|
||||
Enable support for the configuration client model.
|
||||
|
||||
config BT_MESH_HEALTH_CLI
|
||||
bool "Support for Health Client Model"
|
||||
help
|
||||
Enable support for the health client model.
|
||||
|
||||
config BT_MESH_SHELL
|
||||
bool "Enable Bluetooth Mesh shell"
|
||||
select CONSOLE_SHELL
|
||||
depends on BT_MESH_CFG_CLI
|
||||
depends on BT_MESH_HEALTH_CLI
|
||||
help
|
||||
Activate shell module that provides Bluetooth Mesh commands to
|
||||
the console.
|
||||
|
||||
config BT_MESH_DEBUG
|
||||
bool "Enable debug logs"
|
||||
depends on BT_DEBUG
|
||||
help
|
||||
Use this option to enable debug logs for the Bluetooth
|
||||
Mesh functionality.
|
||||
|
||||
if BT_MESH_DEBUG
|
||||
|
||||
config BT_MESH_DEBUG_NET
|
||||
bool "Network layer debug"
|
||||
help
|
||||
Use this option to enable Network layer debug logs for the
|
||||
Bluetooth Mesh functionality.
|
||||
|
||||
config BT_MESH_DEBUG_TRANS
|
||||
bool "Transport layer debug"
|
||||
help
|
||||
Use this option to enable Transport layer debug logs for the
|
||||
Bluetooth Mesh functionality.
|
||||
|
||||
config BT_MESH_DEBUG_BEACON
|
||||
bool "Beacon debug"
|
||||
help
|
||||
Use this option to enable Beacon-related debug logs for the
|
||||
Bluetooth Mesh functionality.
|
||||
|
||||
config BT_MESH_DEBUG_CRYPTO
|
||||
bool "Crypto debug"
|
||||
help
|
||||
Use this option to enable cryptographic debug logs for the
|
||||
Bluetooth Mesh functionality.
|
||||
|
||||
config BT_MESH_DEBUG_PROV
|
||||
bool "Provisioning debug"
|
||||
help
|
||||
Use this option to enable Provisioning debug logs for the
|
||||
Bluetooth Mesh functionality.
|
||||
|
||||
config BT_MESH_DEBUG_ACCESS
|
||||
bool "Access layer debug"
|
||||
help
|
||||
Use this option to enable Access layer and device composition
|
||||
related debug logs for Bluetooth Mesh.
|
||||
|
||||
config BT_MESH_DEBUG_MODEL
|
||||
bool "Foundation model debug"
|
||||
help
|
||||
Use this option to enable debug logs for the Foundation
|
||||
Models.
|
||||
|
||||
config BT_MESH_DEBUG_ADV
|
||||
bool "Advertising debug"
|
||||
help
|
||||
Use this option to enable advertising debug logs for
|
||||
the Bluetooth Mesh functionality.
|
||||
|
||||
config BT_MESH_DEBUG_LOW_POWER
|
||||
bool "Low Power debug"
|
||||
help
|
||||
Use this option to enable Low Power debug logs for the
|
||||
Bluetooth Mesh functionality.
|
||||
|
||||
config BT_MESH_DEBUG_FRIEND
|
||||
bool "Friend debug"
|
||||
help
|
||||
Use this option to enable Friend debug logs for the
|
||||
Bluetooth Mesh functionality.
|
||||
|
||||
config BT_MESH_DEBUG_PROXY
|
||||
bool "Proxy debug"
|
||||
depends on BT_MESH_PROXY
|
||||
help
|
||||
Use this option to enable Proxy protocol debug logs.
|
||||
|
||||
endif # BT_MESH_DEBUG
|
||||
|
||||
endif # BT_MESH
|
||||
13
Living_SDK/kernel/protocols/bluetooth/host/bt_mesh/TODO
Normal file
13
Living_SDK/kernel/protocols/bluetooth/host/bt_mesh/TODO
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
Bluetooth Mesh implementation tasks
|
||||
===================================
|
||||
|
||||
* Persistent storage support
|
||||
|
||||
* Configuration & Health Clients (Configuration is partially done)
|
||||
|
||||
* Provisioner support
|
||||
|
||||
* Any generally useful models from the Model Specification
|
||||
|
||||
* Find a way to overlay provisioning memory with network memory
|
||||
(linker magic?)
|
||||
704
Living_SDK/kernel/protocols/bluetooth/host/bt_mesh/access.c
Normal file
704
Living_SDK/kernel/protocols/bluetooth/host/bt_mesh/access.c
Normal file
|
|
@ -0,0 +1,704 @@
|
|||
/* Bluetooth Mesh */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2017 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <zephyr.h>
|
||||
#include <errno.h>
|
||||
#include <misc/util.h>
|
||||
#include <misc/byteorder.h>
|
||||
|
||||
#include <net/buf.h>
|
||||
#include <bluetooth/bluetooth.h>
|
||||
#include <bluetooth/mesh.h>
|
||||
|
||||
#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_MESH_DEBUG_ACCESS)
|
||||
#include "common/log.h"
|
||||
|
||||
#include "mesh.h"
|
||||
#include "adv.h"
|
||||
#include "net.h"
|
||||
#include "lpn.h"
|
||||
#include "transport.h"
|
||||
#include "access.h"
|
||||
#include "foundation.h"
|
||||
|
||||
static const struct bt_mesh_comp *dev_comp;
|
||||
static u16_t dev_primary_addr;
|
||||
|
||||
static const struct {
|
||||
const u16_t id;
|
||||
int (*const init)(struct bt_mesh_model *model, bool primary);
|
||||
} model_init[] = {
|
||||
{ BT_MESH_MODEL_ID_CFG_SRV, bt_mesh_cfg_srv_init },
|
||||
{ BT_MESH_MODEL_ID_HEALTH_SRV, bt_mesh_health_srv_init },
|
||||
#if defined(CONFIG_BT_MESH_CFG_CLI)
|
||||
{ BT_MESH_MODEL_ID_CFG_CLI, bt_mesh_cfg_cli_init },
|
||||
#endif
|
||||
#if defined(CONFIG_BT_MESH_HEALTH_CLI)
|
||||
{ BT_MESH_MODEL_ID_HEALTH_CLI, bt_mesh_health_cli_init },
|
||||
#endif
|
||||
};
|
||||
|
||||
void bt_mesh_model_foreach(void (*func)(struct bt_mesh_model *mod,
|
||||
struct bt_mesh_elem *elem,
|
||||
bool vnd, bool primary,
|
||||
void *user_data),
|
||||
void *user_data)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
for (i = 0; i < dev_comp->elem_count; i++) {
|
||||
struct bt_mesh_elem *elem = &dev_comp->elem[i];
|
||||
|
||||
for (j = 0; j < elem->model_count; j++) {
|
||||
struct bt_mesh_model *model = &elem->models[j];
|
||||
|
||||
func(model, elem, false, i == 0, user_data);
|
||||
}
|
||||
|
||||
for (j = 0; j < elem->vnd_model_count; j++) {
|
||||
struct bt_mesh_model *model = &elem->vnd_models[j];
|
||||
|
||||
func(model, elem, true, i == 0, user_data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
s32_t bt_mesh_model_pub_period_get(struct bt_mesh_model *mod)
|
||||
{
|
||||
int period;
|
||||
|
||||
if (!mod->pub) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (mod->pub->period >> 6) {
|
||||
case 0x00:
|
||||
/* 1 step is 100 ms */
|
||||
period = K_MSEC((mod->pub->period & BIT_MASK(6)) * 100);
|
||||
break;
|
||||
case 0x01:
|
||||
/* 1 step is 1 second */
|
||||
period = K_SECONDS(mod->pub->period & BIT_MASK(6));
|
||||
break;
|
||||
case 0x02:
|
||||
/* 1 step is 10 seconds */
|
||||
period = K_SECONDS((mod->pub->period & BIT_MASK(6)) * 10);
|
||||
break;
|
||||
case 0x03:
|
||||
/* 1 step is 10 minutes */
|
||||
period = K_MINUTES((mod->pub->period & BIT_MASK(6)) * 10);
|
||||
break;
|
||||
default:
|
||||
CODE_UNREACHABLE;
|
||||
}
|
||||
|
||||
return period >> mod->pub->period_div;
|
||||
}
|
||||
|
||||
static s32_t next_period(struct bt_mesh_model *mod)
|
||||
{
|
||||
struct bt_mesh_model_pub *pub = mod->pub;
|
||||
u32_t elapsed, period;
|
||||
|
||||
period = bt_mesh_model_pub_period_get(mod);
|
||||
if (!period) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
elapsed = k_uptime_get_32() - pub->period_start;
|
||||
|
||||
BT_DBG("Publishing took %ums", elapsed);
|
||||
|
||||
if (elapsed > period) {
|
||||
BT_WARN("Publication sending took longer than the period");
|
||||
/* Return smallest positive number since 0 means disabled */
|
||||
return K_MSEC(1);
|
||||
}
|
||||
|
||||
return period - elapsed;
|
||||
}
|
||||
|
||||
static void publish_sent(int err, void *user_data)
|
||||
{
|
||||
struct bt_mesh_model *mod = user_data;
|
||||
s32_t delay;
|
||||
|
||||
BT_DBG("err %d", err);
|
||||
|
||||
if (mod->pub->count) {
|
||||
delay = BT_MESH_PUB_TRANSMIT_INT(mod->pub->retransmit);
|
||||
} else {
|
||||
delay = next_period(mod);
|
||||
}
|
||||
|
||||
if (delay) {
|
||||
BT_DBG("Publishing next time in %dms", delay);
|
||||
k_delayed_work_submit(&mod->pub->timer, delay);
|
||||
}
|
||||
}
|
||||
|
||||
static const struct bt_mesh_send_cb pub_sent_cb = {
|
||||
.end = publish_sent,
|
||||
};
|
||||
|
||||
static int publish_retransmit(struct bt_mesh_model *mod)
|
||||
{
|
||||
struct net_buf_simple *sdu = NET_BUF_SIMPLE(BT_MESH_TX_SDU_MAX);
|
||||
struct bt_mesh_model_pub *pub = mod->pub;
|
||||
struct bt_mesh_app_key *key;
|
||||
struct bt_mesh_msg_ctx ctx = {
|
||||
.addr = pub->addr,
|
||||
.send_ttl = pub->ttl,
|
||||
};
|
||||
struct bt_mesh_net_tx tx = {
|
||||
.ctx = &ctx,
|
||||
.src = mod->elem->addr,
|
||||
.xmit = bt_mesh_net_transmit_get(),
|
||||
.friend_cred = pub->cred,
|
||||
};
|
||||
|
||||
key = bt_mesh_app_key_find(pub->key);
|
||||
if (!key) {
|
||||
return -EADDRNOTAVAIL;
|
||||
}
|
||||
|
||||
tx.sub = bt_mesh_subnet_get(key->net_idx);
|
||||
|
||||
ctx.net_idx = key->net_idx;
|
||||
ctx.app_idx = key->app_idx;
|
||||
|
||||
net_buf_simple_init(sdu, 0);
|
||||
net_buf_simple_add_mem(sdu, pub->msg->data, pub->msg->len);
|
||||
|
||||
pub->count--;
|
||||
|
||||
return bt_mesh_trans_send(&tx, sdu, &pub_sent_cb, mod);
|
||||
}
|
||||
|
||||
static void mod_publish(struct k_work *work)
|
||||
{
|
||||
struct bt_mesh_model_pub *pub = CONTAINER_OF(work,
|
||||
struct bt_mesh_model_pub,
|
||||
timer.work);
|
||||
s32_t period_ms;
|
||||
int err;
|
||||
|
||||
BT_DBG("");
|
||||
|
||||
period_ms = bt_mesh_model_pub_period_get(pub->mod);
|
||||
BT_DBG("period %u ms", period_ms);
|
||||
|
||||
if (pub->count) {
|
||||
err = publish_retransmit(pub->mod);
|
||||
if (err) {
|
||||
BT_ERR("Failed to retransmit (err %d)", err);
|
||||
|
||||
pub->count = 0;
|
||||
|
||||
/* Continue with normal publication */
|
||||
if (period_ms) {
|
||||
k_delayed_work_submit(&pub->timer, period_ms);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!period_ms) {
|
||||
return;
|
||||
}
|
||||
|
||||
__ASSERT_NO_MSG(pub->update != NULL);
|
||||
|
||||
pub->period_start = k_uptime_get_32();
|
||||
|
||||
err = pub->update(pub->mod);
|
||||
if (err) {
|
||||
BT_ERR("Failed to update publication message");
|
||||
return;
|
||||
}
|
||||
|
||||
err = bt_mesh_model_publish(pub->mod);
|
||||
if (err) {
|
||||
BT_ERR("Publishing failed (err %d)", err);
|
||||
}
|
||||
|
||||
if (pub->count) {
|
||||
/* Retransmissions also control the timer */
|
||||
k_delayed_work_cancel(&pub->timer);
|
||||
}
|
||||
}
|
||||
|
||||
static void mod_init(struct bt_mesh_model *mod, struct bt_mesh_elem *elem,
|
||||
bool vnd, bool primary, void *user_data)
|
||||
{
|
||||
int i;
|
||||
|
||||
mod->elem = elem;
|
||||
|
||||
if (mod->pub) {
|
||||
mod->pub->mod = mod;
|
||||
k_delayed_work_init(&mod->pub->timer, mod_publish);
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(mod->keys); i++) {
|
||||
mod->keys[i] = BT_MESH_KEY_UNUSED;
|
||||
}
|
||||
|
||||
if (vnd) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(model_init); i++) {
|
||||
if (model_init[i].id == mod->id) {
|
||||
model_init[i].init(mod, primary);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int bt_mesh_comp_register(const struct bt_mesh_comp *comp)
|
||||
{
|
||||
/* There must be at least one element */
|
||||
if (!comp->elem_count) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
dev_comp = comp;
|
||||
|
||||
bt_mesh_model_foreach(mod_init, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void bt_mesh_comp_provision(u16_t addr)
|
||||
{
|
||||
int i;
|
||||
|
||||
dev_primary_addr = addr;
|
||||
|
||||
BT_DBG("addr 0x%04x elem_count %zu", addr, dev_comp->elem_count);
|
||||
|
||||
for (i = 0; i < dev_comp->elem_count; i++) {
|
||||
struct bt_mesh_elem *elem = &dev_comp->elem[i];
|
||||
|
||||
elem->addr = addr++;
|
||||
|
||||
BT_DBG("addr 0x%04x mod_count %u vnd_mod_count %u",
|
||||
elem->addr, elem->model_count, elem->vnd_model_count);
|
||||
}
|
||||
}
|
||||
|
||||
void bt_mesh_comp_unprovision(void)
|
||||
{
|
||||
BT_DBG("");
|
||||
|
||||
dev_primary_addr = BT_MESH_ADDR_UNASSIGNED;
|
||||
|
||||
bt_mesh_model_foreach(mod_init, NULL);
|
||||
}
|
||||
|
||||
u16_t bt_mesh_primary_addr(void)
|
||||
{
|
||||
return dev_primary_addr;
|
||||
}
|
||||
|
||||
u16_t *bt_mesh_model_find_group(struct bt_mesh_model *mod, u16_t addr)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(mod->groups); i++) {
|
||||
if (mod->groups[i] == addr) {
|
||||
return &mod->groups[i];
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct bt_mesh_model *bt_mesh_elem_find_group(struct bt_mesh_elem *elem,
|
||||
u16_t group_addr)
|
||||
{
|
||||
struct bt_mesh_model *model;
|
||||
u16_t *match;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < elem->model_count; i++) {
|
||||
model = &elem->models[i];
|
||||
|
||||
match = bt_mesh_model_find_group(model, group_addr);
|
||||
if (match) {
|
||||
return model;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < elem->vnd_model_count; i++) {
|
||||
model = &elem->vnd_models[i];
|
||||
|
||||
match = bt_mesh_model_find_group(model, group_addr);
|
||||
if (match) {
|
||||
return model;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct bt_mesh_elem *bt_mesh_elem_find(u16_t addr)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < dev_comp->elem_count; i++) {
|
||||
struct bt_mesh_elem *elem = &dev_comp->elem[i];
|
||||
|
||||
if (BT_MESH_ADDR_IS_GROUP(addr) ||
|
||||
BT_MESH_ADDR_IS_VIRTUAL(addr)) {
|
||||
if (bt_mesh_elem_find_group(elem, addr)) {
|
||||
return elem;
|
||||
}
|
||||
} else if (elem->addr == addr) {
|
||||
return elem;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
u8_t bt_mesh_elem_count(void)
|
||||
{
|
||||
return dev_comp->elem_count;
|
||||
}
|
||||
|
||||
static bool model_has_key(struct bt_mesh_model *mod, u16_t key)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(mod->keys); i++) {
|
||||
if (mod->keys[i] == key) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static const struct bt_mesh_model_op *find_op(struct bt_mesh_model *models,
|
||||
u8_t model_count,
|
||||
u16_t app_idx, u32_t opcode,
|
||||
struct bt_mesh_model **model)
|
||||
{
|
||||
u8_t i;
|
||||
|
||||
for (i = 0; i < model_count; i++) {
|
||||
const struct bt_mesh_model_op *op;
|
||||
|
||||
*model = &models[i];
|
||||
|
||||
if (!model_has_key(*model, app_idx)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (op = (*model)->op; op->func; op++) {
|
||||
if (op->opcode == opcode) {
|
||||
return op;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*model = NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int get_opcode(struct net_buf_simple *buf, u32_t *opcode)
|
||||
{
|
||||
switch (buf->data[0] >> 6) {
|
||||
case 0x00:
|
||||
case 0x01:
|
||||
if (buf->data[0] == 0x7f) {
|
||||
BT_ERR("Ignoring RFU OpCode");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
*opcode = net_buf_simple_pull_u8(buf);
|
||||
return 0;
|
||||
case 0x02:
|
||||
if (buf->len < 2) {
|
||||
BT_ERR("Too short payload for 2-octet OpCode");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
*opcode = net_buf_simple_pull_be16(buf);
|
||||
return 0;
|
||||
case 0x03:
|
||||
if (buf->len < 3) {
|
||||
BT_ERR("Too short payload for 3-octet OpCode");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
*opcode = net_buf_simple_pull_u8(buf) << 16;
|
||||
*opcode |= net_buf_simple_pull_le16(buf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
CODE_UNREACHABLE;
|
||||
}
|
||||
|
||||
bool bt_mesh_fixed_group_match(u16_t addr)
|
||||
{
|
||||
/* Check for fixed group addresses */
|
||||
switch (addr) {
|
||||
case BT_MESH_ADDR_ALL_NODES:
|
||||
return true;
|
||||
case BT_MESH_ADDR_PROXIES:
|
||||
/* TODO: Proxy not yet supported */
|
||||
return false;
|
||||
case BT_MESH_ADDR_FRIENDS:
|
||||
return (bt_mesh_friend_get() == BT_MESH_FRIEND_ENABLED);
|
||||
case BT_MESH_ADDR_RELAYS:
|
||||
return (bt_mesh_relay_get() == BT_MESH_RELAY_ENABLED);
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void bt_mesh_model_recv(struct bt_mesh_net_rx *rx, struct net_buf_simple *buf)
|
||||
{
|
||||
struct bt_mesh_model *models, *model;
|
||||
const struct bt_mesh_model_op *op;
|
||||
u32_t opcode;
|
||||
u8_t count;
|
||||
int i;
|
||||
|
||||
BT_DBG("app_idx 0x%04x src 0x%04x dst 0x%04x", rx->ctx.app_idx,
|
||||
rx->ctx.addr, rx->dst);
|
||||
BT_DBG("len %u: %s", buf->len, bt_hex(buf->data, buf->len));
|
||||
|
||||
if (get_opcode(buf, &opcode) < 0) {
|
||||
BT_WARN("Unable to decode OpCode");
|
||||
return;
|
||||
}
|
||||
|
||||
BT_DBG("OpCode 0x%08x", opcode);
|
||||
|
||||
for (i = 0; i < dev_comp->elem_count; i++) {
|
||||
struct bt_mesh_elem *elem = &dev_comp->elem[i];
|
||||
|
||||
if (BT_MESH_ADDR_IS_UNICAST(rx->dst)) {
|
||||
if (elem->addr != rx->dst) {
|
||||
continue;
|
||||
}
|
||||
} else if (BT_MESH_ADDR_IS_GROUP(rx->dst) ||
|
||||
BT_MESH_ADDR_IS_VIRTUAL(rx->dst)) {
|
||||
if (!bt_mesh_elem_find_group(elem, rx->dst)) {
|
||||
continue;
|
||||
}
|
||||
} else if (i != 0 || !bt_mesh_fixed_group_match(rx->dst)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* SIG models cannot contain 3-byte (vendor) OpCodes, and
|
||||
* vendor models cannot contain SIG (1- or 2-byte) OpCodes, so
|
||||
* we only need to do the lookup in one of the model lists.
|
||||
*/
|
||||
if (opcode < 0x10000) {
|
||||
models = elem->models;
|
||||
count = elem->model_count;
|
||||
} else {
|
||||
models = elem->vnd_models;
|
||||
count = elem->vnd_model_count;
|
||||
}
|
||||
|
||||
op = find_op(models, count, rx->ctx.app_idx, opcode, &model);
|
||||
if (op) {
|
||||
struct net_buf_simple_state state;
|
||||
|
||||
if (buf->len < op->min_len) {
|
||||
BT_ERR("Too short message for OpCode 0x%08x",
|
||||
opcode);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* The callback will likely parse the buffer, so
|
||||
* store the parsing state in case multiple models
|
||||
* receive the message.
|
||||
*/
|
||||
net_buf_simple_save(buf, &state);
|
||||
op->func(model, &rx->ctx, buf);
|
||||
net_buf_simple_restore(buf, &state);
|
||||
|
||||
} else {
|
||||
BT_DBG("No OpCode 0x%08x for elem %d", opcode, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void bt_mesh_model_msg_init(struct net_buf_simple *msg, u32_t opcode)
|
||||
{
|
||||
net_buf_simple_init(msg, 0);
|
||||
|
||||
if (opcode < 0x100) {
|
||||
/* 1-byte OpCode */
|
||||
net_buf_simple_add_u8(msg, opcode);
|
||||
return;
|
||||
}
|
||||
|
||||
if (opcode < 0x10000) {
|
||||
/* 2-byte OpCode */
|
||||
net_buf_simple_add_be16(msg, opcode);
|
||||
return;
|
||||
}
|
||||
|
||||
/* 3-byte OpCode */
|
||||
net_buf_simple_add_u8(msg, ((opcode >> 16) & 0xff));
|
||||
net_buf_simple_add_le16(msg, opcode & 0xffff);
|
||||
}
|
||||
|
||||
static int model_send(struct bt_mesh_model *model,
|
||||
struct bt_mesh_net_tx *tx, bool implicit_bind,
|
||||
struct net_buf_simple *msg,
|
||||
const struct bt_mesh_send_cb *cb, void *cb_data)
|
||||
{
|
||||
BT_DBG("net_idx 0x%04x app_idx 0x%04x dst 0x%04x", tx->ctx->net_idx,
|
||||
tx->ctx->app_idx, tx->ctx->addr);
|
||||
BT_DBG("len %u: %s", msg->len, bt_hex(msg->data, msg->len));
|
||||
|
||||
if (!bt_mesh_is_provisioned()) {
|
||||
BT_ERR("Local node is not yet provisioned");
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
if (net_buf_simple_tailroom(msg) < 4) {
|
||||
BT_ERR("Not enough tailroom for TransMIC");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (msg->len > BT_MESH_TX_SDU_MAX - 4) {
|
||||
BT_ERR("Too big message");
|
||||
return -EMSGSIZE;
|
||||
}
|
||||
|
||||
if (!implicit_bind && !model_has_key(model, tx->ctx->app_idx)) {
|
||||
BT_ERR("Model not bound to AppKey 0x%04x", tx->ctx->app_idx);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return bt_mesh_trans_send(tx, msg, cb, cb_data);
|
||||
}
|
||||
|
||||
int bt_mesh_model_send(struct bt_mesh_model *model,
|
||||
struct bt_mesh_msg_ctx *ctx,
|
||||
struct net_buf_simple *msg,
|
||||
const struct bt_mesh_send_cb *cb, void *cb_data)
|
||||
{
|
||||
struct bt_mesh_net_tx tx = {
|
||||
.sub = bt_mesh_subnet_get(ctx->net_idx),
|
||||
.ctx = ctx,
|
||||
.src = model->elem->addr,
|
||||
.xmit = bt_mesh_net_transmit_get(),
|
||||
.friend_cred = 0,
|
||||
};
|
||||
|
||||
return model_send(model, &tx, false, msg, cb, cb_data);
|
||||
}
|
||||
|
||||
int bt_mesh_model_publish(struct bt_mesh_model *model)
|
||||
{
|
||||
struct net_buf_simple *sdu = NET_BUF_SIMPLE(BT_MESH_TX_SDU_MAX);
|
||||
struct bt_mesh_model_pub *pub = model->pub;
|
||||
struct bt_mesh_app_key *key;
|
||||
struct bt_mesh_msg_ctx ctx = {
|
||||
};
|
||||
struct bt_mesh_net_tx tx = {
|
||||
.ctx = &ctx,
|
||||
.src = model->elem->addr,
|
||||
.xmit = bt_mesh_net_transmit_get(),
|
||||
};
|
||||
int err;
|
||||
|
||||
BT_DBG("");
|
||||
|
||||
if (!pub) {
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
if (pub->addr == BT_MESH_ADDR_UNASSIGNED) {
|
||||
return -EADDRNOTAVAIL;
|
||||
}
|
||||
|
||||
key = bt_mesh_app_key_find(pub->key);
|
||||
if (!key) {
|
||||
return -EADDRNOTAVAIL;
|
||||
}
|
||||
|
||||
if (pub->msg->len + 4 > BT_MESH_TX_SDU_MAX) {
|
||||
BT_ERR("Message does not fit maximum SDU size");
|
||||
return -EMSGSIZE;
|
||||
}
|
||||
|
||||
if (pub->count) {
|
||||
BT_WARN("Clearing publish retransmit timer");
|
||||
k_delayed_work_cancel(&pub->timer);
|
||||
}
|
||||
|
||||
net_buf_simple_init(sdu, 0);
|
||||
net_buf_simple_add_mem(sdu, pub->msg->data, pub->msg->len);
|
||||
|
||||
ctx.addr = pub->addr;
|
||||
ctx.send_ttl = pub->ttl;
|
||||
ctx.net_idx = key->net_idx;
|
||||
ctx.app_idx = key->app_idx;
|
||||
|
||||
tx.friend_cred = pub->cred;
|
||||
tx.sub = bt_mesh_subnet_get(ctx.net_idx),
|
||||
|
||||
pub->count = BT_MESH_PUB_TRANSMIT_COUNT(pub->retransmit);
|
||||
|
||||
BT_DBG("Publish Retransmit Count %u Interval %ums", pub->count,
|
||||
BT_MESH_PUB_TRANSMIT_INT(pub->retransmit));
|
||||
|
||||
err = model_send(model, &tx, true, sdu, &pub_sent_cb, model);
|
||||
if (err) {
|
||||
pub->count = 0;
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct bt_mesh_model *bt_mesh_model_find_vnd(struct bt_mesh_elem *elem,
|
||||
u16_t company, u16_t id)
|
||||
{
|
||||
u8_t i;
|
||||
|
||||
for (i = 0; i < elem->vnd_model_count; i++) {
|
||||
if (elem->vnd_models[i].vnd.company == company &&
|
||||
elem->vnd_models[i].vnd.id == id) {
|
||||
return &elem->vnd_models[i];
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct bt_mesh_model *bt_mesh_model_find(struct bt_mesh_elem *elem,
|
||||
u16_t id)
|
||||
{
|
||||
u8_t i;
|
||||
|
||||
for (i = 0; i < elem->model_count; i++) {
|
||||
if (elem->models[i].id == id) {
|
||||
return &elem->models[i];
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const struct bt_mesh_comp *bt_mesh_comp_get(void)
|
||||
{
|
||||
return dev_comp;
|
||||
}
|
||||
42
Living_SDK/kernel/protocols/bluetooth/host/bt_mesh/access.h
Normal file
42
Living_SDK/kernel/protocols/bluetooth/host/bt_mesh/access.h
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
/* Bluetooth Mesh */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2017 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
void bt_mesh_elem_register(struct bt_mesh_elem *elem, u8_t count);
|
||||
|
||||
u8_t bt_mesh_elem_count(void);
|
||||
|
||||
/* Find local element based on unicast or group address */
|
||||
struct bt_mesh_elem *bt_mesh_elem_find(u16_t addr);
|
||||
|
||||
struct bt_mesh_model *bt_mesh_model_find_vnd(struct bt_mesh_elem *elem,
|
||||
u16_t company, u16_t id);
|
||||
struct bt_mesh_model *bt_mesh_model_find(struct bt_mesh_elem *elem,
|
||||
u16_t id);
|
||||
|
||||
u16_t *bt_mesh_model_find_group(struct bt_mesh_model *mod, u16_t addr);
|
||||
|
||||
bool bt_mesh_fixed_group_match(u16_t addr);
|
||||
|
||||
void bt_mesh_model_foreach(void (*func)(struct bt_mesh_model *mod,
|
||||
struct bt_mesh_elem *elem,
|
||||
bool vnd, bool primary,
|
||||
void *user_data),
|
||||
void *user_data);
|
||||
|
||||
s32_t bt_mesh_model_pub_period_get(struct bt_mesh_model *mod);
|
||||
|
||||
void bt_mesh_comp_provision(u16_t addr);
|
||||
void bt_mesh_comp_unprovision(void);
|
||||
|
||||
u16_t bt_mesh_primary_addr(void);
|
||||
|
||||
const struct bt_mesh_comp *bt_mesh_comp_get(void);
|
||||
|
||||
void bt_mesh_model_recv(struct bt_mesh_net_rx *rx, struct net_buf_simple *buf);
|
||||
|
||||
int bt_mesh_comp_register(const struct bt_mesh_comp *comp);
|
||||
315
Living_SDK/kernel/protocols/bluetooth/host/bt_mesh/adv.c
Normal file
315
Living_SDK/kernel/protocols/bluetooth/host/bt_mesh/adv.c
Normal file
|
|
@ -0,0 +1,315 @@
|
|||
/* Bluetooth Mesh */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2017 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <zephyr.h>
|
||||
#include <misc/stack.h>
|
||||
#include <misc/util.h>
|
||||
|
||||
#include <net/buf.h>
|
||||
#include <bluetooth/bluetooth.h>
|
||||
#include <bluetooth/hci.h>
|
||||
#include <bluetooth/conn.h>
|
||||
#include <bluetooth/mesh.h>
|
||||
|
||||
#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_MESH_DEBUG_ADV)
|
||||
#include "common/log.h"
|
||||
|
||||
#include "../hci_core.h"
|
||||
|
||||
#include "adv.h"
|
||||
#include "foundation.h"
|
||||
#include "net.h"
|
||||
#include "beacon.h"
|
||||
#include "prov.h"
|
||||
#include "proxy.h"
|
||||
|
||||
/* Window and Interval are equal for continuous scanning */
|
||||
#define MESH_SCAN_INTERVAL 0x10
|
||||
#define MESH_SCAN_WINDOW 0x10
|
||||
|
||||
/* Convert from ms to 0.625ms units */
|
||||
#define ADV_INT(_ms) ((_ms) * 8 / 5)
|
||||
|
||||
/* Pre-5.0 controllers enforce a minimum interval of 100ms
|
||||
* whereas 5.0+ controllers can go down to 20ms.
|
||||
*/
|
||||
#define ADV_INT_DEFAULT K_MSEC(100)
|
||||
#define ADV_INT_FAST K_MSEC(20)
|
||||
|
||||
/* TinyCrypt PRNG consumes a lot of stack space, so we need to have
|
||||
* an increased call stack whenever it's used.
|
||||
*/
|
||||
#if defined(CONFIG_BT_HOST_CRYPTO)
|
||||
#define ADV_STACK_SIZE 768
|
||||
#else
|
||||
#define ADV_STACK_SIZE 512
|
||||
#endif
|
||||
|
||||
static K_FIFO_DEFINE(adv_queue);
|
||||
static struct k_thread adv_thread_data;
|
||||
static BT_STACK_NOINIT(adv_thread_stack, ADV_STACK_SIZE);
|
||||
|
||||
static const u8_t adv_type[] = {
|
||||
[BT_MESH_ADV_PROV] = BT_DATA_MESH_PROV,
|
||||
[BT_MESH_ADV_DATA] = BT_DATA_MESH_MESSAGE,
|
||||
[BT_MESH_ADV_BEACON] = BT_DATA_MESH_BEACON,
|
||||
};
|
||||
|
||||
#if 0
|
||||
NET_BUF_POOL_DEFINE(adv_buf_pool, CONFIG_BT_MESH_ADV_BUF_COUNT,
|
||||
BT_MESH_ADV_DATA_SIZE, BT_MESH_ADV_USER_DATA_SIZE, NULL);
|
||||
#endif
|
||||
extern struct net_buf_pool adv_buf_pool;
|
||||
|
||||
static struct bt_mesh_adv adv_pool[CONFIG_BT_MESH_ADV_BUF_COUNT];
|
||||
|
||||
static struct bt_mesh_adv *adv_alloc(int id)
|
||||
{
|
||||
return &adv_pool[id];
|
||||
}
|
||||
|
||||
static inline void adv_send_start(u16_t duration, int err,
|
||||
const struct bt_mesh_send_cb *cb,
|
||||
void *cb_data)
|
||||
{
|
||||
if (cb && cb->start) {
|
||||
cb->start(duration, err, cb_data);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void adv_send_end(int err, const struct bt_mesh_send_cb *cb,
|
||||
void *cb_data)
|
||||
{
|
||||
if (cb && cb->end) {
|
||||
cb->end(err, cb_data);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void adv_send(struct net_buf *buf)
|
||||
{
|
||||
const s32_t adv_int_min = ((bt_dev.hci_version >= BT_HCI_VERSION_5_0) ?
|
||||
ADV_INT_FAST : ADV_INT_DEFAULT);
|
||||
const struct bt_mesh_send_cb *cb = BT_MESH_ADV(buf)->cb;
|
||||
void *cb_data = BT_MESH_ADV(buf)->cb_data;
|
||||
struct bt_le_adv_param param;
|
||||
u16_t duration, adv_int;
|
||||
struct bt_data ad;
|
||||
int err;
|
||||
|
||||
adv_int = max(adv_int_min, BT_MESH_ADV(buf)->adv_int);
|
||||
duration = (BT_MESH_ADV(buf)->count + 1) * (adv_int + 10);
|
||||
|
||||
BT_DBG("type %u len %u: %s", BT_MESH_ADV(buf)->type,
|
||||
buf->len, bt_hex(buf->data, buf->len));
|
||||
BT_DBG("count %u interval %ums duration %ums",
|
||||
BT_MESH_ADV(buf)->count + 1, adv_int, duration);
|
||||
|
||||
ad.type = adv_type[BT_MESH_ADV(buf)->type];
|
||||
ad.data_len = buf->len;
|
||||
ad.data = buf->data;
|
||||
|
||||
param.options = 0;
|
||||
param.interval_min = ADV_INT(adv_int);
|
||||
param.interval_max = param.interval_min;
|
||||
param.own_addr = NULL;
|
||||
|
||||
err = bt_le_adv_start(¶m, &ad, 1, NULL, 0);
|
||||
net_buf_unref(buf);
|
||||
adv_send_start(duration, err, cb, cb_data);
|
||||
if (err) {
|
||||
BT_ERR("Advertising failed: err %d", err);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
BT_DBG("Advertising started. Sleeping %u ms", duration);
|
||||
|
||||
k_sleep(duration);
|
||||
|
||||
exit:
|
||||
err = bt_le_adv_stop();
|
||||
adv_send_end(err, cb, cb_data);
|
||||
if (err) {
|
||||
BT_ERR("Stopping advertising failed: err %d", err);
|
||||
return;
|
||||
}
|
||||
|
||||
BT_DBG("Advertising stopped");
|
||||
}
|
||||
|
||||
static void adv_thread(void *p1, void *p2, void *p3)
|
||||
{
|
||||
BT_DBG("started");
|
||||
|
||||
while (1) {
|
||||
struct net_buf *buf;
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_MESH_PROXY)) {
|
||||
buf = net_buf_get(&adv_queue, K_NO_WAIT);
|
||||
while (!buf) {
|
||||
s32_t timeout;
|
||||
|
||||
timeout = bt_mesh_proxy_adv_start();
|
||||
BT_DBG("Proxy Advertising up to %d ms",
|
||||
timeout);
|
||||
buf = net_buf_get(&adv_queue, timeout);
|
||||
bt_mesh_proxy_adv_stop();
|
||||
}
|
||||
} else {
|
||||
buf = net_buf_get(&adv_queue, K_FOREVER);
|
||||
}
|
||||
|
||||
if (!buf) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* busy == 0 means this was canceled */
|
||||
if (BT_MESH_ADV(buf)->busy) {
|
||||
BT_MESH_ADV(buf)->busy = 0;
|
||||
adv_send(buf);
|
||||
}
|
||||
|
||||
STACK_ANALYZE("adv stack", adv_thread_stack);
|
||||
k_call_stacks_analyze();
|
||||
|
||||
/* Give other threads a chance to run */
|
||||
k_yield();
|
||||
}
|
||||
}
|
||||
|
||||
void bt_mesh_adv_update(void)
|
||||
{
|
||||
BT_DBG("");
|
||||
|
||||
k_fifo_cancel_wait(&adv_queue);
|
||||
}
|
||||
|
||||
struct net_buf *bt_mesh_adv_create_from_pool(struct net_buf_pool *pool,
|
||||
bt_mesh_adv_alloc_t get_id,
|
||||
enum bt_mesh_adv_type type,
|
||||
u8_t xmit_count, u8_t xmit_int,
|
||||
s32_t timeout)
|
||||
{
|
||||
struct bt_mesh_adv *adv;
|
||||
struct net_buf *buf;
|
||||
|
||||
buf = net_buf_alloc(pool, timeout);
|
||||
if (!buf) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
adv = get_id(net_buf_id(buf));
|
||||
BT_MESH_ADV(buf) = adv;
|
||||
|
||||
memset(adv, 0, sizeof(*adv));
|
||||
|
||||
adv->type = type;
|
||||
adv->count = xmit_count;
|
||||
adv->adv_int = xmit_int;
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
struct net_buf *bt_mesh_adv_create(enum bt_mesh_adv_type type, u8_t xmit_count,
|
||||
u8_t xmit_int, s32_t timeout)
|
||||
{
|
||||
return bt_mesh_adv_create_from_pool(&adv_buf_pool, adv_alloc, type,
|
||||
xmit_count, xmit_int, timeout);
|
||||
}
|
||||
|
||||
void bt_mesh_adv_send(struct net_buf *buf, const struct bt_mesh_send_cb *cb,
|
||||
void *cb_data)
|
||||
{
|
||||
BT_DBG("type 0x%02x len %u: %s", BT_MESH_ADV(buf)->type, buf->len,
|
||||
bt_hex(buf->data, buf->len));
|
||||
|
||||
BT_MESH_ADV(buf)->cb = cb;
|
||||
BT_MESH_ADV(buf)->cb_data = cb_data;
|
||||
BT_MESH_ADV(buf)->busy = 1;
|
||||
|
||||
net_buf_put(&adv_queue, net_buf_ref(buf));
|
||||
}
|
||||
|
||||
static void bt_mesh_scan_cb(const bt_addr_le_t *addr, s8_t rssi,
|
||||
u8_t adv_type, struct net_buf_simple *buf)
|
||||
{
|
||||
if (adv_type != BT_LE_ADV_NONCONN_IND) {
|
||||
return;
|
||||
}
|
||||
|
||||
BT_DBG("len %u: %s", buf->len, bt_hex(buf->data, buf->len));
|
||||
|
||||
while (buf->len > 1) {
|
||||
struct net_buf_simple_state state;
|
||||
u8_t len, type;
|
||||
|
||||
len = net_buf_simple_pull_u8(buf);
|
||||
/* Check for early termination */
|
||||
if (len == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (len > buf->len || buf->len < 1) {
|
||||
BT_WARN("AD malformed");
|
||||
return;
|
||||
}
|
||||
|
||||
net_buf_simple_save(buf, &state);
|
||||
|
||||
type = net_buf_simple_pull_u8(buf);
|
||||
|
||||
buf->len = len - 1;
|
||||
|
||||
switch (type) {
|
||||
case BT_DATA_MESH_MESSAGE:
|
||||
bt_mesh_net_recv(buf, rssi, BT_MESH_NET_IF_ADV);
|
||||
break;
|
||||
#if defined(CONFIG_BT_MESH_PB_ADV)
|
||||
case BT_DATA_MESH_PROV:
|
||||
bt_mesh_pb_adv_recv(buf);
|
||||
break;
|
||||
#endif
|
||||
case BT_DATA_MESH_BEACON:
|
||||
bt_mesh_beacon_recv(buf);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
net_buf_simple_restore(buf, &state);
|
||||
net_buf_simple_pull(buf, len);
|
||||
}
|
||||
}
|
||||
|
||||
void bt_mesh_adv_init(void)
|
||||
{
|
||||
k_fifo_init(&adv_queue);
|
||||
k_lifo_init(&adv_buf_pool.free);
|
||||
k_thread_create(&adv_thread_data, adv_thread_stack,
|
||||
K_THREAD_STACK_SIZEOF(adv_thread_stack), adv_thread,
|
||||
NULL, NULL, NULL, CONFIG_BT_MESH_ADV_PRIO, 0, K_NO_WAIT);
|
||||
}
|
||||
|
||||
int bt_mesh_scan_enable(void)
|
||||
{
|
||||
struct bt_le_scan_param scan_param = {
|
||||
.type = BT_HCI_LE_SCAN_PASSIVE,
|
||||
.filter_dup = BT_HCI_LE_SCAN_FILTER_DUP_DISABLE,
|
||||
.interval = MESH_SCAN_INTERVAL,
|
||||
.window = MESH_SCAN_WINDOW };
|
||||
|
||||
BT_DBG("");
|
||||
|
||||
return bt_le_scan_start(&scan_param, bt_mesh_scan_cb);
|
||||
}
|
||||
|
||||
int bt_mesh_scan_disable(void)
|
||||
{
|
||||
BT_DBG("");
|
||||
|
||||
return bt_le_scan_stop();
|
||||
}
|
||||
66
Living_SDK/kernel/protocols/bluetooth/host/bt_mesh/adv.h
Normal file
66
Living_SDK/kernel/protocols/bluetooth/host/bt_mesh/adv.h
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
/* Bluetooth Mesh */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2017 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/* Maximum advertising data payload for a single data type */
|
||||
#define BT_MESH_ADV_DATA_SIZE 29
|
||||
|
||||
/* The user data is a pointer (4 bytes) to struct bt_mesh_adv */
|
||||
#define BT_MESH_ADV_USER_DATA_SIZE 4
|
||||
|
||||
#define BT_MESH_ADV(buf) (*(struct bt_mesh_adv **)net_buf_user_data(buf))
|
||||
|
||||
enum bt_mesh_adv_type {
|
||||
BT_MESH_ADV_PROV,
|
||||
BT_MESH_ADV_DATA,
|
||||
BT_MESH_ADV_BEACON,
|
||||
};
|
||||
|
||||
typedef void (*bt_mesh_adv_func_t)(struct net_buf *buf, u16_t duration,
|
||||
int err, void *user_data);
|
||||
|
||||
struct bt_mesh_adv {
|
||||
const struct bt_mesh_send_cb *cb;
|
||||
void *cb_data;
|
||||
|
||||
u8_t type:2,
|
||||
busy:1;
|
||||
u8_t count:3,
|
||||
adv_int:5;
|
||||
union {
|
||||
/* Address, used e.g. for Friend Queue messages */
|
||||
u16_t addr;
|
||||
|
||||
/* For transport layer segment sending */
|
||||
struct {
|
||||
u8_t attempts;
|
||||
} seg;
|
||||
};
|
||||
};
|
||||
|
||||
typedef struct bt_mesh_adv *(*bt_mesh_adv_alloc_t)(int id);
|
||||
|
||||
/* xmit_count: Number of retransmissions, i.e. 0 == 1 transmission */
|
||||
struct net_buf *bt_mesh_adv_create(enum bt_mesh_adv_type type, u8_t xmit_count,
|
||||
u8_t xmit_int, s32_t timeout);
|
||||
|
||||
struct net_buf *bt_mesh_adv_create_from_pool(struct net_buf_pool *pool,
|
||||
bt_mesh_adv_alloc_t get_id,
|
||||
enum bt_mesh_adv_type type,
|
||||
u8_t xmit_count, u8_t xmit_int,
|
||||
s32_t timeout);
|
||||
|
||||
void bt_mesh_adv_send(struct net_buf *buf, const struct bt_mesh_send_cb *cb,
|
||||
void *cb_data);
|
||||
|
||||
void bt_mesh_adv_update(void);
|
||||
|
||||
void bt_mesh_adv_init(void);
|
||||
|
||||
int bt_mesh_scan_enable(void);
|
||||
|
||||
int bt_mesh_scan_disable(void);
|
||||
385
Living_SDK/kernel/protocols/bluetooth/host/bt_mesh/beacon.c
Normal file
385
Living_SDK/kernel/protocols/bluetooth/host/bt_mesh/beacon.c
Normal file
|
|
@ -0,0 +1,385 @@
|
|||
/* Bluetooth Mesh */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2017 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <zephyr.h>
|
||||
#include <errno.h>
|
||||
#include <misc/util.h>
|
||||
|
||||
#include <net/buf.h>
|
||||
#include <bluetooth/bluetooth.h>
|
||||
#include <bluetooth/conn.h>
|
||||
#include <bluetooth/mesh.h>
|
||||
|
||||
#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_MESH_DEBUG_BEACON)
|
||||
#include "common/log.h"
|
||||
|
||||
#include "adv.h"
|
||||
#include "mesh.h"
|
||||
#include "net.h"
|
||||
#include "prov.h"
|
||||
#include "crypto.h"
|
||||
#include "beacon.h"
|
||||
#include "foundation.h"
|
||||
|
||||
#define UNPROVISIONED_INTERVAL K_SECONDS(5)
|
||||
#define PROVISIONED_INTERVAL K_SECONDS(10)
|
||||
|
||||
#define BEACON_TYPE_UNPROVISIONED 0x00
|
||||
#define BEACON_TYPE_SECURE 0x01
|
||||
|
||||
/* 3 transmissions, 20ms interval */
|
||||
#define UNPROV_XMIT_COUNT 2
|
||||
#define UNPROV_XMIT_INT 20
|
||||
|
||||
/* 1 transmission, 20ms interval */
|
||||
#define PROV_XMIT_COUNT 0
|
||||
#define PROV_XMIT_INT 20
|
||||
|
||||
static struct k_delayed_work beacon_timer;
|
||||
|
||||
static struct bt_mesh_subnet *cache_check(u8_t data[21])
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) {
|
||||
struct bt_mesh_subnet *sub = &bt_mesh.sub[i];
|
||||
|
||||
if (sub->net_idx == BT_MESH_KEY_UNUSED) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!memcmp(sub->beacon_cache, data, 21)) {
|
||||
return sub;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void cache_add(u8_t data[21], struct bt_mesh_subnet *sub)
|
||||
{
|
||||
memcpy(sub->beacon_cache, data, 21);
|
||||
}
|
||||
|
||||
static void beacon_complete(int err, void *user_data)
|
||||
{
|
||||
struct bt_mesh_subnet *sub = user_data;
|
||||
|
||||
BT_DBG("err %d", err);
|
||||
|
||||
sub->beacon_sent = k_uptime_get_32();
|
||||
}
|
||||
|
||||
void bt_mesh_beacon_create(struct bt_mesh_subnet *sub,
|
||||
struct net_buf_simple *buf)
|
||||
{
|
||||
u8_t flags = bt_mesh_net_flags(sub);
|
||||
struct bt_mesh_subnet_keys *keys;
|
||||
|
||||
net_buf_simple_add_u8(buf, BEACON_TYPE_SECURE);
|
||||
|
||||
if (sub->kr_flag) {
|
||||
keys = &sub->keys[1];
|
||||
} else {
|
||||
keys = &sub->keys[0];
|
||||
}
|
||||
|
||||
net_buf_simple_add_u8(buf, flags);
|
||||
|
||||
/* Network ID */
|
||||
net_buf_simple_add_mem(buf, keys->net_id, 8);
|
||||
|
||||
/* IV Index */
|
||||
net_buf_simple_add_be32(buf, bt_mesh.iv_index);
|
||||
|
||||
net_buf_simple_add_mem(buf, sub->auth, 8);
|
||||
|
||||
BT_DBG("net_idx 0x%04x flags 0x%02x NetID %s", sub->net_idx,
|
||||
flags, bt_hex(keys->net_id, 8));
|
||||
BT_DBG("IV Index 0x%08x Auth %s", bt_mesh.iv_index,
|
||||
bt_hex(sub->auth, 8));
|
||||
}
|
||||
|
||||
/* If the interval has passed or is within 5 seconds from now send a beacon */
|
||||
#define BEACON_THRESHOLD(sub) (K_SECONDS(10 * ((sub)->beacons_last + 1)) - \
|
||||
K_SECONDS(5))
|
||||
|
||||
static int secure_beacon_send(void)
|
||||
{
|
||||
static const struct bt_mesh_send_cb send_cb = {
|
||||
.end = beacon_complete,
|
||||
};
|
||||
u32_t now = k_uptime_get_32();
|
||||
int i;
|
||||
|
||||
BT_DBG("");
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) {
|
||||
struct bt_mesh_subnet *sub = &bt_mesh.sub[i];
|
||||
struct net_buf *buf;
|
||||
u32_t time_diff;
|
||||
|
||||
if (sub->net_idx == BT_MESH_KEY_UNUSED) {
|
||||
continue;
|
||||
}
|
||||
|
||||
time_diff = now - sub->beacon_sent;
|
||||
if (time_diff < K_SECONDS(600) &&
|
||||
time_diff < BEACON_THRESHOLD(sub)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
buf = bt_mesh_adv_create(BT_MESH_ADV_BEACON, PROV_XMIT_COUNT,
|
||||
PROV_XMIT_INT, K_NO_WAIT);
|
||||
if (!buf) {
|
||||
BT_ERR("Unable to allocate beacon buffer");
|
||||
return -ENOBUFS;
|
||||
}
|
||||
|
||||
bt_mesh_beacon_create(sub, &buf->b);
|
||||
|
||||
bt_mesh_adv_send(buf, &send_cb, sub);
|
||||
net_buf_unref(buf);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int unprovisioned_beacon_send(void)
|
||||
{
|
||||
#if defined(CONFIG_BT_MESH_PB_ADV)
|
||||
struct net_buf *buf;
|
||||
|
||||
BT_DBG("");
|
||||
|
||||
buf = bt_mesh_adv_create(BT_MESH_ADV_BEACON, UNPROV_XMIT_COUNT,
|
||||
UNPROV_XMIT_INT, K_NO_WAIT);
|
||||
if (!buf) {
|
||||
BT_ERR("Unable to allocate beacon buffer");
|
||||
return -ENOBUFS;
|
||||
}
|
||||
|
||||
net_buf_add_u8(buf, BEACON_TYPE_UNPROVISIONED);
|
||||
net_buf_add_mem(buf, bt_mesh_prov_get_uuid(), 16);
|
||||
|
||||
/* OOB Info (2 bytes) + URI Hash (4 bytes) */
|
||||
memset(net_buf_add(buf, 2 + 4), 0, 2 + 4);
|
||||
|
||||
bt_mesh_adv_send(buf, NULL, NULL);
|
||||
net_buf_unref(buf);
|
||||
|
||||
#endif /* CONFIG_BT_MESH_PB_ADV */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void update_beacon_observation(void)
|
||||
{
|
||||
static bool first_half;
|
||||
int i;
|
||||
|
||||
/* Observation period is 20 seconds, whereas the beacon timer
|
||||
* runs every 10 seconds. We process what's happened during the
|
||||
* window only after the seconnd half.
|
||||
*/
|
||||
first_half = !first_half;
|
||||
if (first_half) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) {
|
||||
struct bt_mesh_subnet *sub = &bt_mesh.sub[i];
|
||||
|
||||
if (sub->net_idx == BT_MESH_KEY_UNUSED) {
|
||||
continue;
|
||||
}
|
||||
|
||||
sub->beacons_last = sub->beacons_cur;
|
||||
sub->beacons_cur = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void beacon_send(struct k_work *work)
|
||||
{
|
||||
/* Don't send anything if we have an active provisioning link */
|
||||
if (IS_ENABLED(CONFIG_BT_MESH_PROV) && bt_prov_active()) {
|
||||
k_delayed_work_submit(&beacon_timer, UNPROVISIONED_INTERVAL);
|
||||
return;
|
||||
}
|
||||
|
||||
BT_DBG("");
|
||||
|
||||
if (bt_mesh_is_provisioned()) {
|
||||
update_beacon_observation();
|
||||
secure_beacon_send();
|
||||
|
||||
/* Only resubmit if beaconing is still enabled */
|
||||
if (bt_mesh_beacon_get() == BT_MESH_BEACON_ENABLED ||
|
||||
bt_mesh.ivu_initiator) {
|
||||
k_delayed_work_submit(&beacon_timer,
|
||||
PROVISIONED_INTERVAL);
|
||||
}
|
||||
} else {
|
||||
unprovisioned_beacon_send();
|
||||
k_delayed_work_submit(&beacon_timer, UNPROVISIONED_INTERVAL);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void secure_beacon_recv(struct net_buf_simple *buf)
|
||||
{
|
||||
u8_t *data, *net_id, *auth;
|
||||
struct bt_mesh_subnet *sub;
|
||||
u32_t iv_index;
|
||||
bool new_key, kr_change, iv_change;
|
||||
u8_t flags;
|
||||
|
||||
if (buf->len < 21) {
|
||||
BT_ERR("Too short secure beacon (len %u)", buf->len);
|
||||
return;
|
||||
}
|
||||
|
||||
sub = cache_check(buf->data);
|
||||
if (sub) {
|
||||
/* We've seen this beacon before - just update the stats */
|
||||
goto update_stats;
|
||||
}
|
||||
|
||||
/* So we can add to the cache if auth matches */
|
||||
data = buf->data;
|
||||
|
||||
flags = net_buf_simple_pull_u8(buf);
|
||||
net_id = buf->data;
|
||||
net_buf_simple_pull(buf, 8);
|
||||
iv_index = net_buf_simple_pull_be32(buf);
|
||||
auth = buf->data;
|
||||
|
||||
BT_DBG("flags 0x%02x id %s iv_index 0x%08x",
|
||||
flags, bt_hex(net_id, 8), iv_index);
|
||||
|
||||
sub = bt_mesh_subnet_find(net_id, flags, iv_index, auth, &new_key);
|
||||
if (!sub) {
|
||||
BT_DBG("No subnet that matched beacon");
|
||||
return;
|
||||
}
|
||||
|
||||
if (sub->kr_phase == BT_MESH_KR_PHASE_2 && !new_key) {
|
||||
BT_WARN("Ignoring Phase 2 KR Update secured using old key");
|
||||
return;
|
||||
}
|
||||
|
||||
cache_add(data, sub);
|
||||
|
||||
/* If we have NetKey0 accept initiation only from it */
|
||||
if (bt_mesh_subnet_get(BT_MESH_KEY_PRIMARY) &&
|
||||
sub->net_idx != BT_MESH_KEY_PRIMARY) {
|
||||
BT_WARN("Ignoring secure beacon on non-primary subnet");
|
||||
goto update_stats;
|
||||
}
|
||||
|
||||
BT_DBG("net_idx 0x%04x iv_index 0x%08x, current iv_index 0x%08x",
|
||||
sub->net_idx, iv_index, bt_mesh.iv_index);
|
||||
|
||||
if (bt_mesh.ivu_initiator &&
|
||||
bt_mesh.iv_update == BT_MESH_IV_UPDATE(flags)) {
|
||||
bt_mesh_beacon_ivu_initiator(false);
|
||||
}
|
||||
|
||||
iv_change = bt_mesh_net_iv_update(iv_index, BT_MESH_IV_UPDATE(flags));
|
||||
|
||||
kr_change = bt_mesh_kr_update(sub, BT_MESH_KEY_REFRESH(flags), new_key);
|
||||
if (kr_change) {
|
||||
bt_mesh_net_beacon_update(sub);
|
||||
}
|
||||
|
||||
if (iv_change) {
|
||||
/* Update all subnets */
|
||||
bt_mesh_net_sec_update(NULL);
|
||||
} else if (kr_change) {
|
||||
/* Key Refresh without IV Update only impacts one subnet */
|
||||
bt_mesh_net_sec_update(sub);
|
||||
}
|
||||
|
||||
update_stats:
|
||||
if (bt_mesh_beacon_get() == BT_MESH_BEACON_ENABLED &&
|
||||
sub->beacons_cur < 0xff) {
|
||||
sub->beacons_cur++;
|
||||
}
|
||||
}
|
||||
|
||||
void bt_mesh_beacon_recv(struct net_buf_simple *buf)
|
||||
{
|
||||
u8_t type;
|
||||
|
||||
BT_DBG("%u bytes: %s", buf->len, bt_hex(buf->data, buf->len));
|
||||
|
||||
if (buf->len < 1) {
|
||||
BT_ERR("Too short beacon");
|
||||
return;
|
||||
}
|
||||
|
||||
type = net_buf_simple_pull_u8(buf);
|
||||
switch (type) {
|
||||
case BEACON_TYPE_UNPROVISIONED:
|
||||
BT_DBG("Ignoring unprovisioned device beacon");
|
||||
break;
|
||||
case BEACON_TYPE_SECURE:
|
||||
secure_beacon_recv(buf);
|
||||
break;
|
||||
default:
|
||||
BT_WARN("Unknown beacon type 0x%02x", type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bt_mesh_beacon_init(void)
|
||||
{
|
||||
k_delayed_work_init(&beacon_timer, beacon_send);
|
||||
}
|
||||
|
||||
void bt_mesh_beacon_ivu_initiator(bool enable)
|
||||
{
|
||||
bt_mesh.ivu_initiator = enable;
|
||||
|
||||
if (enable) {
|
||||
k_work_submit(&beacon_timer.work);
|
||||
} else if (bt_mesh_beacon_get() == BT_MESH_BEACON_DISABLED) {
|
||||
k_delayed_work_cancel(&beacon_timer);
|
||||
}
|
||||
}
|
||||
|
||||
void bt_mesh_beacon_enable(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!bt_mesh_is_provisioned()) {
|
||||
k_work_submit(&beacon_timer.work);
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) {
|
||||
struct bt_mesh_subnet *sub = &bt_mesh.sub[i];
|
||||
|
||||
if (sub->net_idx == BT_MESH_KEY_UNUSED) {
|
||||
continue;
|
||||
}
|
||||
|
||||
sub->beacons_last = 0;
|
||||
sub->beacons_cur = 0;
|
||||
|
||||
bt_mesh_net_beacon_update(sub);
|
||||
}
|
||||
|
||||
k_work_submit(&beacon_timer.work);
|
||||
}
|
||||
|
||||
void bt_mesh_beacon_disable(void)
|
||||
{
|
||||
if (!bt_mesh.ivu_initiator) {
|
||||
k_delayed_work_cancel(&beacon_timer);
|
||||
}
|
||||
}
|
||||
19
Living_SDK/kernel/protocols/bluetooth/host/bt_mesh/beacon.h
Normal file
19
Living_SDK/kernel/protocols/bluetooth/host/bt_mesh/beacon.h
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
/* Bluetooth Mesh */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2017 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
void bt_mesh_beacon_enable(void);
|
||||
void bt_mesh_beacon_disable(void);
|
||||
|
||||
void bt_mesh_beacon_ivu_initiator(bool enable);
|
||||
|
||||
void bt_mesh_beacon_recv(struct net_buf_simple *buf);
|
||||
|
||||
void bt_mesh_beacon_create(struct bt_mesh_subnet *sub,
|
||||
struct net_buf_simple *buf);
|
||||
|
||||
void bt_mesh_beacon_init(void);
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
NAME := bt_mesh
|
||||
|
||||
$(NAME)_TYPE := kernel
|
||||
GLOBAL_INCLUDES += .
|
||||
|
||||
$(NAME)_INCLUDES += ../../common/tinycrypt/include/ \
|
||||
../../include/bluetooth/mesh/
|
||||
|
||||
$(NAME)_COMPONENTS += yloop
|
||||
|
||||
$(NAME)_SOURCES := main.c \
|
||||
adv.c \
|
||||
beacon.c \
|
||||
net.c \
|
||||
transport.c \
|
||||
crypto.c \
|
||||
access.c \
|
||||
cfg_srv.c \
|
||||
health_srv.c \
|
||||
cfg_cli.c \
|
||||
proxy.c \
|
||||
prov.c
|
||||
1403
Living_SDK/kernel/protocols/bluetooth/host/bt_mesh/cfg_cli.c
Normal file
1403
Living_SDK/kernel/protocols/bluetooth/host/bt_mesh/cfg_cli.c
Normal file
File diff suppressed because it is too large
Load diff
3238
Living_SDK/kernel/protocols/bluetooth/host/bt_mesh/cfg_srv.c
Normal file
3238
Living_SDK/kernel/protocols/bluetooth/host/bt_mesh/cfg_srv.c
Normal file
File diff suppressed because it is too large
Load diff
875
Living_SDK/kernel/protocols/bluetooth/host/bt_mesh/crypto.c
Normal file
875
Living_SDK/kernel/protocols/bluetooth/host/bt_mesh/crypto.c
Normal file
|
|
@ -0,0 +1,875 @@
|
|||
/* Bluetooth Mesh */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2017 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
#include <errno.h>
|
||||
#include <toolchain.h>
|
||||
#include <zephyr/types.h>
|
||||
#include <misc/byteorder.h>
|
||||
#include <misc/util.h>
|
||||
|
||||
#include <tinycrypt/constants.h>
|
||||
#include <tinycrypt/utils.h>
|
||||
#include <tinycrypt/aes.h>
|
||||
#include <tinycrypt/cmac_mode.h>
|
||||
#include <tinycrypt/ccm_mode.h>
|
||||
|
||||
#include <bluetooth/mesh.h>
|
||||
#include <bluetooth/crypto.h>
|
||||
|
||||
#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_MESH_DEBUG_CRYPTO)
|
||||
#include "common/log.h"
|
||||
|
||||
#include "mesh.h"
|
||||
#include "crypto.h"
|
||||
|
||||
#define NET_MIC_LEN(pdu) (((pdu)[1] & 0x80) ? 8 : 4)
|
||||
#define APP_MIC_LEN(aszmic) ((aszmic) ? 8 : 4)
|
||||
|
||||
int bt_mesh_aes_cmac(const u8_t key[16], struct bt_mesh_sg *sg,
|
||||
size_t sg_len, u8_t mac[16])
|
||||
{
|
||||
struct tc_aes_key_sched_struct sched;
|
||||
struct tc_cmac_struct state;
|
||||
|
||||
if (tc_cmac_setup(&state, key, &sched) == TC_CRYPTO_FAIL) {
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
for (; sg_len; sg_len--, sg++) {
|
||||
if (tc_cmac_update(&state, sg->data,
|
||||
sg->len) == TC_CRYPTO_FAIL) {
|
||||
return -EIO;
|
||||
}
|
||||
}
|
||||
|
||||
if (tc_cmac_final(mac, &state) == TC_CRYPTO_FAIL) {
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bt_mesh_k1(const u8_t *ikm, size_t ikm_len, const u8_t salt[16],
|
||||
const char *info, u8_t okm[16])
|
||||
{
|
||||
int err;
|
||||
|
||||
err = bt_mesh_aes_cmac_one(salt, ikm, ikm_len, okm);
|
||||
if (err < 0) {
|
||||
return err;
|
||||
}
|
||||
|
||||
return bt_mesh_aes_cmac_one(okm, info, strlen(info), okm);
|
||||
}
|
||||
|
||||
int bt_mesh_k2(const u8_t n[16], const u8_t *p, size_t p_len,
|
||||
u8_t net_id[1], u8_t enc_key[16], u8_t priv_key[16])
|
||||
{
|
||||
struct bt_mesh_sg sg[3];
|
||||
u8_t salt[16];
|
||||
u8_t out[16];
|
||||
u8_t t[16];
|
||||
u8_t pad;
|
||||
int err;
|
||||
|
||||
BT_DBG("n %s", bt_hex(n, 16));
|
||||
BT_DBG("p %s", bt_hex(p, p_len));
|
||||
|
||||
err = bt_mesh_s1("smk2", salt);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
err = bt_mesh_aes_cmac_one(salt, n, 16, t);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
pad = 0x01;
|
||||
|
||||
sg[0].data = NULL;
|
||||
sg[0].len = 0;
|
||||
sg[1].data = p;
|
||||
sg[1].len = p_len;
|
||||
sg[2].data = &pad;
|
||||
sg[2].len = sizeof(pad);
|
||||
|
||||
err = bt_mesh_aes_cmac(t, sg, ARRAY_SIZE(sg), out);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
net_id[0] = out[15] & 0x7f;
|
||||
|
||||
sg[0].data = out;
|
||||
sg[0].len = sizeof(out);
|
||||
pad = 0x02;
|
||||
|
||||
err = bt_mesh_aes_cmac(t, sg, ARRAY_SIZE(sg), out);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
memcpy(enc_key, out, 16);
|
||||
|
||||
pad = 0x03;
|
||||
|
||||
err = bt_mesh_aes_cmac(t, sg, ARRAY_SIZE(sg), out);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
memcpy(priv_key, out, 16);
|
||||
|
||||
BT_DBG("NID 0x%02x enc_key %s", net_id[0], bt_hex(enc_key, 16));
|
||||
BT_DBG("priv_key %s", bt_hex(priv_key, 16));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bt_mesh_k3(const u8_t n[16], u8_t out[8])
|
||||
{
|
||||
u8_t id64[] = { 'i', 'd', '6', '4', 0x01 };
|
||||
u8_t tmp[16];
|
||||
u8_t t[16];
|
||||
int err;
|
||||
|
||||
err = bt_mesh_s1("smk3", tmp);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
err = bt_mesh_aes_cmac_one(tmp, n, 16, t);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
err = bt_mesh_aes_cmac_one(t, id64, sizeof(id64), tmp);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
memcpy(out, tmp + 8, 8);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bt_mesh_k4(const u8_t n[16], u8_t out[1])
|
||||
{
|
||||
u8_t id6[] = { 'i', 'd', '6', 0x01 };
|
||||
u8_t tmp[16];
|
||||
u8_t t[16];
|
||||
int err;
|
||||
|
||||
err = bt_mesh_s1("smk4", tmp);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
err = bt_mesh_aes_cmac_one(tmp, n, 16, t);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
err = bt_mesh_aes_cmac_one(t, id6, sizeof(id6), tmp);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
out[0] = tmp[15] & BIT_MASK(6);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bt_mesh_id128(const u8_t n[16], const char *s, u8_t out[16])
|
||||
{
|
||||
const char *id128 = "id128\x01";
|
||||
u8_t salt[16];
|
||||
int err;
|
||||
|
||||
err = bt_mesh_s1(s, salt);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
return bt_mesh_k1(n, 16, salt, id128, out);
|
||||
}
|
||||
|
||||
static int bt_mesh_ccm_decrypt(const u8_t key[16], u8_t nonce[13],
|
||||
const u8_t *enc_msg, size_t msg_len,
|
||||
const u8_t *aad, size_t aad_len,
|
||||
u8_t *out_msg, size_t mic_size)
|
||||
{
|
||||
u8_t msg[16], pmsg[16], cmic[16], cmsg[16], Xn[16], mic[16];
|
||||
u16_t last_blk, blk_cnt;
|
||||
size_t i, j;
|
||||
int err;
|
||||
|
||||
if (msg_len < 1 || aad_len >= 0xff00) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* C_mic = e(AppKey, 0x01 || nonce || 0x0000) */
|
||||
pmsg[0] = 0x01;
|
||||
memcpy(pmsg + 1, nonce, 13);
|
||||
sys_put_be16(0x0000, pmsg + 14);
|
||||
|
||||
err = bt_encrypt_be(key, pmsg, cmic);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
/* X_0 = e(AppKey, 0x09 || nonce || length) */
|
||||
if (mic_size == sizeof(u64_t)) {
|
||||
pmsg[0] = 0x19 | (aad_len ? 0x40 : 0x00);
|
||||
} else {
|
||||
pmsg[0] = 0x09 | (aad_len ? 0x40 : 0x00);
|
||||
}
|
||||
|
||||
memcpy(pmsg + 1, nonce, 13);
|
||||
sys_put_be16(msg_len, pmsg + 14);
|
||||
|
||||
err = bt_encrypt_be(key, pmsg, Xn);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
/* If AAD is being used to authenticate, include it here */
|
||||
if (aad_len) {
|
||||
sys_put_be16(aad_len, pmsg);
|
||||
|
||||
for (i = 0; i < sizeof(u16_t); i++) {
|
||||
pmsg[i] = Xn[i] ^ pmsg[i];
|
||||
}
|
||||
|
||||
j = 0;
|
||||
aad_len += sizeof(u16_t);
|
||||
while (aad_len > 16) {
|
||||
do {
|
||||
pmsg[i] = Xn[i] ^ aad[j];
|
||||
i++, j++;
|
||||
} while (i < 16);
|
||||
|
||||
aad_len -= 16;
|
||||
i = 0;
|
||||
|
||||
err = bt_encrypt_be(key, pmsg, Xn);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < aad_len; i++, j++) {
|
||||
pmsg[i] = Xn[i] ^ aad[j];
|
||||
}
|
||||
|
||||
for (i = aad_len; i < 16; i++) {
|
||||
pmsg[i] = Xn[i];
|
||||
}
|
||||
|
||||
err = bt_encrypt_be(key, pmsg, Xn);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
last_blk = msg_len % 16;
|
||||
blk_cnt = (msg_len + 15) / 16;
|
||||
if (!last_blk) {
|
||||
last_blk = 16;
|
||||
}
|
||||
|
||||
for (j = 0; j < blk_cnt; j++) {
|
||||
if (j + 1 == blk_cnt) {
|
||||
/* C_1 = e(AppKey, 0x01 || nonce || 0x0001) */
|
||||
pmsg[0] = 0x01;
|
||||
memcpy(pmsg + 1, nonce, 13);
|
||||
sys_put_be16(j + 1, pmsg + 14);
|
||||
|
||||
err = bt_encrypt_be(key, pmsg, cmsg);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Encrypted = Payload[0-15] ^ C_1 */
|
||||
for (i = 0; i < last_blk; i++) {
|
||||
msg[i] = enc_msg[(j * 16) + i] ^ cmsg[i];
|
||||
}
|
||||
|
||||
memcpy(out_msg + (j * 16), msg, last_blk);
|
||||
|
||||
/* X_1 = e(AppKey, X_0 ^ Payload[0-15]) */
|
||||
for (i = 0; i < last_blk; i++) {
|
||||
pmsg[i] = Xn[i] ^ msg[i];
|
||||
}
|
||||
|
||||
for (i = last_blk; i < 16; i++) {
|
||||
pmsg[i] = Xn[i] ^ 0x00;
|
||||
}
|
||||
|
||||
err = bt_encrypt_be(key, pmsg, Xn);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
/* MIC = C_mic ^ X_1 */
|
||||
for (i = 0; i < sizeof(mic); i++) {
|
||||
mic[i] = cmic[i] ^ Xn[i];
|
||||
}
|
||||
} else {
|
||||
/* C_1 = e(AppKey, 0x01 || nonce || 0x0001) */
|
||||
pmsg[0] = 0x01;
|
||||
memcpy(pmsg + 1, nonce, 13);
|
||||
sys_put_be16(j + 1, pmsg + 14);
|
||||
|
||||
err = bt_encrypt_be(key, pmsg, cmsg);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Encrypted = Payload[0-15] ^ C_1 */
|
||||
for (i = 0; i < 16; i++) {
|
||||
msg[i] = enc_msg[(j * 16) + i] ^ cmsg[i];
|
||||
}
|
||||
|
||||
memcpy(out_msg + (j * 16), msg, 16);
|
||||
|
||||
/* X_1 = e(AppKey, X_0 ^ Payload[0-15]) */
|
||||
for (i = 0; i < 16; i++) {
|
||||
pmsg[i] = Xn[i] ^ msg[i];
|
||||
}
|
||||
|
||||
err = bt_encrypt_be(key, pmsg, Xn);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (memcmp(mic, enc_msg + msg_len, mic_size)) {
|
||||
return -EBADMSG;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bt_mesh_ccm_encrypt(const u8_t key[16], u8_t nonce[13],
|
||||
const u8_t *msg, size_t msg_len,
|
||||
const u8_t *aad, size_t aad_len,
|
||||
u8_t *out_msg, size_t mic_size)
|
||||
{
|
||||
u8_t pmsg[16], cmic[16], cmsg[16], mic[16], Xn[16];
|
||||
u16_t blk_cnt, last_blk;
|
||||
size_t i, j;
|
||||
int err;
|
||||
|
||||
BT_DBG("key %s", bt_hex(key, 16));
|
||||
BT_DBG("nonce %s", bt_hex(nonce, 13));
|
||||
BT_DBG("msg (len %zu) %s", msg_len, bt_hex(msg, msg_len));
|
||||
BT_DBG("aad_len %zu mic_size %zu", aad_len, mic_size);
|
||||
|
||||
/* Unsupported AAD size */
|
||||
if (aad_len >= 0xff00) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* C_mic = e(AppKey, 0x01 || nonce || 0x0000) */
|
||||
pmsg[0] = 0x01;
|
||||
memcpy(pmsg + 1, nonce, 13);
|
||||
sys_put_be16(0x0000, pmsg + 14);
|
||||
|
||||
err = bt_encrypt_be(key, pmsg, cmic);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
/* X_0 = e(AppKey, 0x09 || nonce || length) */
|
||||
if (mic_size == sizeof(u64_t)) {
|
||||
pmsg[0] = 0x19 | (aad_len ? 0x40 : 0x00);
|
||||
} else {
|
||||
pmsg[0] = 0x09 | (aad_len ? 0x40 : 0x00);
|
||||
}
|
||||
|
||||
memcpy(pmsg + 1, nonce, 13);
|
||||
sys_put_be16(msg_len, pmsg + 14);
|
||||
|
||||
err = bt_encrypt_be(key, pmsg, Xn);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
/* If AAD is being used to authenticate, include it here */
|
||||
if (aad_len) {
|
||||
sys_put_be16(aad_len, pmsg);
|
||||
|
||||
for (i = 0; i < sizeof(u16_t); i++) {
|
||||
pmsg[i] = Xn[i] ^ pmsg[i];
|
||||
}
|
||||
|
||||
j = 0;
|
||||
aad_len += sizeof(u16_t);
|
||||
while (aad_len > 16) {
|
||||
do {
|
||||
pmsg[i] = Xn[i] ^ aad[j];
|
||||
i++, j++;
|
||||
} while (i < 16);
|
||||
|
||||
aad_len -= 16;
|
||||
i = 0;
|
||||
|
||||
err = bt_encrypt_be(key, pmsg, Xn);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < aad_len; i++, j++) {
|
||||
pmsg[i] = Xn[i] ^ aad[j];
|
||||
}
|
||||
|
||||
for (i = aad_len; i < 16; i++) {
|
||||
pmsg[i] = Xn[i];
|
||||
}
|
||||
|
||||
err = bt_encrypt_be(key, pmsg, Xn);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
last_blk = msg_len % 16;
|
||||
blk_cnt = (msg_len + 15) / 16;
|
||||
if (!last_blk) {
|
||||
last_blk = 16;
|
||||
}
|
||||
|
||||
for (j = 0; j < blk_cnt; j++) {
|
||||
if (j + 1 == blk_cnt) {
|
||||
/* X_1 = e(AppKey, X_0 ^ Payload[0-15]) */
|
||||
for (i = 0; i < last_blk; i++) {
|
||||
pmsg[i] = Xn[i] ^ msg[(j * 16) + i];
|
||||
}
|
||||
for (i = last_blk; i < 16; i++) {
|
||||
pmsg[i] = Xn[i] ^ 0x00;
|
||||
}
|
||||
|
||||
err = bt_encrypt_be(key, pmsg, Xn);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
/* MIC = C_mic ^ X_1 */
|
||||
for (i = 0; i < sizeof(mic); i++) {
|
||||
mic[i] = cmic[i] ^ Xn[i];
|
||||
}
|
||||
|
||||
/* C_1 = e(AppKey, 0x01 || nonce || 0x0001) */
|
||||
pmsg[0] = 0x01;
|
||||
memcpy(pmsg + 1, nonce, 13);
|
||||
sys_put_be16(j + 1, pmsg + 14);
|
||||
|
||||
err = bt_encrypt_be(key, pmsg, cmsg);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Encrypted = Payload[0-15] ^ C_1 */
|
||||
for (i = 0; i < last_blk; i++) {
|
||||
out_msg[(j * 16) + i] =
|
||||
msg[(j * 16) + i] ^ cmsg[i];
|
||||
}
|
||||
} else {
|
||||
/* X_1 = e(AppKey, X_0 ^ Payload[0-15]) */
|
||||
for (i = 0; i < 16; i++) {
|
||||
pmsg[i] = Xn[i] ^ msg[(j * 16) + i];
|
||||
}
|
||||
|
||||
err = bt_encrypt_be(key, pmsg, Xn);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
/* C_1 = e(AppKey, 0x01 || nonce || 0x0001) */
|
||||
pmsg[0] = 0x01;
|
||||
memcpy(pmsg + 1, nonce, 13);
|
||||
sys_put_be16(j + 1, pmsg + 14);
|
||||
|
||||
err = bt_encrypt_be(key, pmsg, cmsg);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Encrypted = Payload[0-15] ^ C_N */
|
||||
for (i = 0; i < 16; i++) {
|
||||
out_msg[(j * 16) + i] =
|
||||
msg[(j * 16) + i] ^ cmsg[i];
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
memcpy(out_msg + msg_len, mic, mic_size);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_BT_MESH_PROXY)
|
||||
static void create_proxy_nonce(u8_t nonce[13], const u8_t *pdu,
|
||||
u32_t iv_index)
|
||||
{
|
||||
/* Nonce Type */
|
||||
nonce[0] = 0x03;
|
||||
|
||||
/* Pad */
|
||||
nonce[1] = 0x00;
|
||||
|
||||
/* Sequence Number */
|
||||
nonce[2] = pdu[2];
|
||||
nonce[3] = pdu[3];
|
||||
nonce[4] = pdu[4];
|
||||
|
||||
/* Source Address */
|
||||
nonce[5] = pdu[5];
|
||||
nonce[6] = pdu[6];
|
||||
|
||||
/* Pad */
|
||||
nonce[7] = 0;
|
||||
nonce[8] = 0;
|
||||
|
||||
/* IV Index */
|
||||
sys_put_be32(iv_index, &nonce[9]);
|
||||
}
|
||||
#endif /* PROXY */
|
||||
|
||||
static void create_net_nonce(u8_t nonce[13], const u8_t *pdu,
|
||||
u32_t iv_index)
|
||||
{
|
||||
/* Nonce Type */
|
||||
nonce[0] = 0x00;
|
||||
|
||||
/* FRND + TTL */
|
||||
nonce[1] = pdu[1];
|
||||
|
||||
/* Sequence Number */
|
||||
nonce[2] = pdu[2];
|
||||
nonce[3] = pdu[3];
|
||||
nonce[4] = pdu[4];
|
||||
|
||||
/* Source Address */
|
||||
nonce[5] = pdu[5];
|
||||
nonce[6] = pdu[6];
|
||||
|
||||
/* Pad */
|
||||
nonce[7] = 0;
|
||||
nonce[8] = 0;
|
||||
|
||||
/* IV Index */
|
||||
sys_put_be32(iv_index, &nonce[9]);
|
||||
}
|
||||
|
||||
int bt_mesh_net_obfuscate(u8_t *pdu, u32_t iv_index,
|
||||
const u8_t privacy_key[16])
|
||||
{
|
||||
u8_t priv_rand[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, };
|
||||
u8_t tmp[16];
|
||||
int err, i;
|
||||
|
||||
BT_DBG("IVIndex %u, PrivacyKey %s", iv_index, bt_hex(privacy_key, 16));
|
||||
|
||||
sys_put_be32(iv_index, &priv_rand[5]);
|
||||
memcpy(&priv_rand[9], &pdu[7], 7);
|
||||
|
||||
BT_DBG("PrivacyRandom %s", bt_hex(priv_rand, 16));
|
||||
|
||||
err = bt_encrypt_be(privacy_key, priv_rand, tmp);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
for (i = 0; i < 6; i++) {
|
||||
pdu[1 + i] ^= tmp[i];
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bt_mesh_net_encrypt(const u8_t key[16], struct net_buf_simple *buf,
|
||||
u32_t iv_index, bool proxy)
|
||||
{
|
||||
u8_t mic_len = NET_MIC_LEN(buf->data);
|
||||
u8_t nonce[13];
|
||||
int err;
|
||||
|
||||
BT_DBG("IVIndex %u EncKey %s mic_len %u", iv_index, bt_hex(key, 16),
|
||||
mic_len);
|
||||
BT_DBG("PDU (len %u) %s", buf->len, bt_hex(buf->data, buf->len));
|
||||
|
||||
#if defined(CONFIG_BT_MESH_PROXY)
|
||||
if (proxy) {
|
||||
create_proxy_nonce(nonce, buf->data, iv_index);
|
||||
} else {
|
||||
create_net_nonce(nonce, buf->data, iv_index);
|
||||
}
|
||||
#else
|
||||
create_net_nonce(nonce, buf->data, iv_index);
|
||||
#endif
|
||||
|
||||
BT_DBG("Nonce %s", bt_hex(nonce, 13));
|
||||
|
||||
err = bt_mesh_ccm_encrypt(key, nonce, &buf->data[7], buf->len - 7,
|
||||
NULL, 0, &buf->data[7], mic_len);
|
||||
if (!err) {
|
||||
net_buf_simple_add(buf, mic_len);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
int bt_mesh_net_decrypt(const u8_t key[16], struct net_buf_simple *buf,
|
||||
u32_t iv_index, bool proxy)
|
||||
{
|
||||
u8_t mic_len = NET_MIC_LEN(buf->data);
|
||||
u8_t nonce[13];
|
||||
|
||||
BT_DBG("PDU (%u bytes) %s", buf->len, bt_hex(buf->data, buf->len));
|
||||
BT_DBG("iv_index %u, key %s mic_len %u", iv_index, bt_hex(key, 16),
|
||||
mic_len);
|
||||
|
||||
#if defined(CONFIG_BT_MESH_PROXY)
|
||||
if (proxy) {
|
||||
create_proxy_nonce(nonce, buf->data, iv_index);
|
||||
} else {
|
||||
create_net_nonce(nonce, buf->data, iv_index);
|
||||
}
|
||||
#else
|
||||
create_net_nonce(nonce, buf->data, iv_index);
|
||||
#endif
|
||||
|
||||
BT_DBG("Nonce %s", bt_hex(nonce, 13));
|
||||
|
||||
buf->len -= mic_len;
|
||||
|
||||
return bt_mesh_ccm_decrypt(key, nonce, &buf->data[7], buf->len - 7,
|
||||
NULL, 0, &buf->data[7], mic_len);
|
||||
}
|
||||
|
||||
static void create_app_nonce(u8_t nonce[13], bool dev_key, u8_t aszmic,
|
||||
u16_t src, u16_t dst, u32_t seq_num,
|
||||
u32_t iv_index)
|
||||
{
|
||||
if (dev_key) {
|
||||
nonce[0] = 0x02;
|
||||
} else {
|
||||
nonce[0] = 0x01;
|
||||
}
|
||||
|
||||
sys_put_be32((seq_num | ((u32_t)aszmic << 31)), &nonce[1]);
|
||||
|
||||
sys_put_be16(src, &nonce[5]);
|
||||
sys_put_be16(dst, &nonce[7]);
|
||||
|
||||
sys_put_be32(iv_index, &nonce[9]);
|
||||
}
|
||||
|
||||
int bt_mesh_app_encrypt(const u8_t key[16], bool dev_key, u8_t aszmic,
|
||||
struct net_buf_simple *buf, const u8_t *ad,
|
||||
u16_t src, u16_t dst, u32_t seq_num, u32_t iv_index)
|
||||
{
|
||||
u8_t nonce[13];
|
||||
int err;
|
||||
|
||||
BT_DBG("AppKey %s", bt_hex(key, 16));
|
||||
BT_DBG("dev_key %u src 0x%04x dst 0x%04x", dev_key, src, dst);
|
||||
BT_DBG("seq_num 0x%08x iv_index 0x%08x", seq_num, iv_index);
|
||||
BT_DBG("Clear: %s", bt_hex(buf->data, buf->len));
|
||||
|
||||
create_app_nonce(nonce, dev_key, aszmic, src, dst, seq_num, iv_index);
|
||||
|
||||
BT_DBG("Nonce %s", bt_hex(nonce, 13));
|
||||
|
||||
err = bt_mesh_ccm_encrypt(key, nonce, buf->data, buf->len, ad,
|
||||
ad ? 16 : 0, buf->data, APP_MIC_LEN(aszmic));
|
||||
if (!err) {
|
||||
net_buf_simple_add(buf, APP_MIC_LEN(aszmic));
|
||||
BT_DBG("Encr: %s", bt_hex(buf->data, buf->len));
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
int bt_mesh_app_decrypt(const u8_t key[16], bool dev_key, u8_t aszmic,
|
||||
struct net_buf_simple *buf, struct net_buf_simple *out,
|
||||
const u8_t *ad, u16_t src, u16_t dst, u32_t seq_num,
|
||||
u32_t iv_index)
|
||||
{
|
||||
u8_t nonce[13];
|
||||
int err;
|
||||
|
||||
BT_DBG("EncData (len %u) %s", buf->len, bt_hex(buf->data, buf->len));
|
||||
|
||||
create_app_nonce(nonce, dev_key, aszmic, src, dst, seq_num, iv_index);
|
||||
|
||||
BT_DBG("AppKey %s", bt_hex(key, 16));
|
||||
BT_DBG("Nonce %s", bt_hex(nonce, 13));
|
||||
|
||||
err = bt_mesh_ccm_decrypt(key, nonce, buf->data, buf->len, ad,
|
||||
ad ? 16 : 0, out->data, APP_MIC_LEN(aszmic));
|
||||
if (!err) {
|
||||
net_buf_simple_add(out, buf->len);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/* reversed, 8-bit, poly=0x07 */
|
||||
static const u8_t crc_table[256] = {
|
||||
0x00, 0x91, 0xe3, 0x72, 0x07, 0x96, 0xe4, 0x75,
|
||||
0x0e, 0x9f, 0xed, 0x7c, 0x09, 0x98, 0xea, 0x7b,
|
||||
0x1c, 0x8d, 0xff, 0x6e, 0x1b, 0x8a, 0xf8, 0x69,
|
||||
0x12, 0x83, 0xf1, 0x60, 0x15, 0x84, 0xf6, 0x67,
|
||||
|
||||
0x38, 0xa9, 0xdb, 0x4a, 0x3f, 0xae, 0xdc, 0x4d,
|
||||
0x36, 0xa7, 0xd5, 0x44, 0x31, 0xa0, 0xd2, 0x43,
|
||||
0x24, 0xb5, 0xc7, 0x56, 0x23, 0xb2, 0xc0, 0x51,
|
||||
0x2a, 0xbb, 0xc9, 0x58, 0x2d, 0xbc, 0xce, 0x5f,
|
||||
|
||||
0x70, 0xe1, 0x93, 0x02, 0x77, 0xe6, 0x94, 0x05,
|
||||
0x7e, 0xef, 0x9d, 0x0c, 0x79, 0xe8, 0x9a, 0x0b,
|
||||
0x6c, 0xfd, 0x8f, 0x1e, 0x6b, 0xfa, 0x88, 0x19,
|
||||
0x62, 0xf3, 0x81, 0x10, 0x65, 0xf4, 0x86, 0x17,
|
||||
|
||||
0x48, 0xd9, 0xab, 0x3a, 0x4f, 0xde, 0xac, 0x3d,
|
||||
0x46, 0xd7, 0xa5, 0x34, 0x41, 0xd0, 0xa2, 0x33,
|
||||
0x54, 0xc5, 0xb7, 0x26, 0x53, 0xc2, 0xb0, 0x21,
|
||||
0x5a, 0xcb, 0xb9, 0x28, 0x5d, 0xcc, 0xbe, 0x2f,
|
||||
|
||||
0xe0, 0x71, 0x03, 0x92, 0xe7, 0x76, 0x04, 0x95,
|
||||
0xee, 0x7f, 0x0d, 0x9c, 0xe9, 0x78, 0x0a, 0x9b,
|
||||
0xfc, 0x6d, 0x1f, 0x8e, 0xfb, 0x6a, 0x18, 0x89,
|
||||
0xf2, 0x63, 0x11, 0x80, 0xf5, 0x64, 0x16, 0x87,
|
||||
|
||||
0xd8, 0x49, 0x3b, 0xaa, 0xdf, 0x4e, 0x3c, 0xad,
|
||||
0xd6, 0x47, 0x35, 0xa4, 0xd1, 0x40, 0x32, 0xa3,
|
||||
0xc4, 0x55, 0x27, 0xb6, 0xc3, 0x52, 0x20, 0xb1,
|
||||
0xca, 0x5b, 0x29, 0xb8, 0xcd, 0x5c, 0x2e, 0xbf,
|
||||
|
||||
0x90, 0x01, 0x73, 0xe2, 0x97, 0x06, 0x74, 0xe5,
|
||||
0x9e, 0x0f, 0x7d, 0xec, 0x99, 0x08, 0x7a, 0xeb,
|
||||
0x8c, 0x1d, 0x6f, 0xfe, 0x8b, 0x1a, 0x68, 0xf9,
|
||||
0x82, 0x13, 0x61, 0xf0, 0x85, 0x14, 0x66, 0xf7,
|
||||
|
||||
0xa8, 0x39, 0x4b, 0xda, 0xaf, 0x3e, 0x4c, 0xdd,
|
||||
0xa6, 0x37, 0x45, 0xd4, 0xa1, 0x30, 0x42, 0xd3,
|
||||
0xb4, 0x25, 0x57, 0xc6, 0xb3, 0x22, 0x50, 0xc1,
|
||||
0xba, 0x2b, 0x59, 0xc8, 0xbd, 0x2c, 0x5e, 0xcf
|
||||
};
|
||||
|
||||
u8_t bt_mesh_fcs_calc(const u8_t *data, u8_t data_len)
|
||||
{
|
||||
u8_t fcs = 0xff;
|
||||
|
||||
while (data_len--) {
|
||||
fcs = crc_table[fcs ^ *data++];
|
||||
}
|
||||
|
||||
BT_DBG("fcs 0x%02x", 0xff - fcs);
|
||||
|
||||
return 0xff - fcs;
|
||||
}
|
||||
|
||||
bool bt_mesh_fcs_check(struct net_buf_simple *buf, u8_t received_fcs)
|
||||
{
|
||||
const u8_t *data = buf->data;
|
||||
u16_t data_len = buf->len;
|
||||
u8_t fcs = 0xff;
|
||||
|
||||
while (data_len--) {
|
||||
fcs = crc_table[fcs ^ *data++];
|
||||
}
|
||||
|
||||
return crc_table[fcs ^ received_fcs] == 0xcf;
|
||||
}
|
||||
|
||||
int bt_mesh_virtual_addr(const u8_t virtual_label[16], u16_t *addr)
|
||||
{
|
||||
u8_t salt[16];
|
||||
u8_t tmp[16];
|
||||
int err;
|
||||
|
||||
err = bt_mesh_s1("vtad", salt);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
err = bt_mesh_aes_cmac_one(salt, virtual_label, 16, tmp);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
*addr = (sys_get_be16(&tmp[14]) & 0x3fff) | 0x8000;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bt_mesh_prov_conf_salt(const u8_t conf_inputs[145], u8_t salt[16])
|
||||
{
|
||||
const u8_t conf_salt_key[16] = { 0 };
|
||||
|
||||
return bt_mesh_aes_cmac_one(conf_salt_key, conf_inputs, 145, salt);
|
||||
}
|
||||
|
||||
int bt_mesh_prov_conf_key(const u8_t dhkey[32], const u8_t conf_salt[16],
|
||||
u8_t conf_key[16])
|
||||
{
|
||||
return bt_mesh_k1(dhkey, 32, conf_salt, "prck", conf_key);
|
||||
}
|
||||
|
||||
int bt_mesh_prov_conf(const u8_t conf_key[16], const u8_t rand[16],
|
||||
const u8_t auth[16], u8_t conf[16])
|
||||
{
|
||||
struct bt_mesh_sg sg[] = { { rand, 16 }, { auth, 16 } };
|
||||
|
||||
BT_DBG("ConfirmationKey %s", bt_hex(conf_key, 16));
|
||||
BT_DBG("RandomDevice %s", bt_hex(rand, 16));
|
||||
BT_DBG("AuthValue %s", bt_hex(auth, 16));
|
||||
|
||||
return bt_mesh_aes_cmac(conf_key, sg, ARRAY_SIZE(sg), conf);
|
||||
}
|
||||
|
||||
int bt_mesh_prov_decrypt(const u8_t key[16], u8_t nonce[13],
|
||||
const u8_t data[25 + 8], u8_t out[25])
|
||||
{
|
||||
return bt_mesh_ccm_decrypt(key, nonce, data, 25, NULL, 0, out, 8);
|
||||
}
|
||||
|
||||
int bt_mesh_beacon_auth(const u8_t beacon_key[16], u8_t flags,
|
||||
const u8_t net_id[8], u32_t iv_index,
|
||||
u8_t auth[8])
|
||||
{
|
||||
u8_t msg[13], tmp[16];
|
||||
int err;
|
||||
|
||||
BT_DBG("BeaconKey %s", bt_hex(beacon_key, 16));
|
||||
BT_DBG("NetId %s", bt_hex(net_id, 8));
|
||||
BT_DBG("IV Index 0x%08x", iv_index);
|
||||
|
||||
msg[0] = flags;
|
||||
memcpy(&msg[1], net_id, 8);
|
||||
sys_put_be32(iv_index, &msg[9]);
|
||||
|
||||
BT_DBG("BeaconMsg %s", bt_hex(msg, sizeof(msg)));
|
||||
|
||||
err = bt_mesh_aes_cmac_one(beacon_key, msg, sizeof(msg), tmp);
|
||||
if (!err) {
|
||||
memcpy(auth, tmp, 8);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
154
Living_SDK/kernel/protocols/bluetooth/host/bt_mesh/crypto.h
Normal file
154
Living_SDK/kernel/protocols/bluetooth/host/bt_mesh/crypto.h
Normal file
|
|
@ -0,0 +1,154 @@
|
|||
/* Bluetooth Mesh */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2017 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
struct bt_mesh_sg {
|
||||
const void *data;
|
||||
size_t len;
|
||||
};
|
||||
|
||||
int bt_mesh_aes_cmac(const u8_t key[16], struct bt_mesh_sg *sg,
|
||||
size_t sg_len, u8_t mac[16]);
|
||||
|
||||
static inline int bt_mesh_aes_cmac_one(const u8_t key[16], const void *m,
|
||||
size_t len, u8_t mac[16])
|
||||
{
|
||||
struct bt_mesh_sg sg = { m, len };
|
||||
|
||||
return bt_mesh_aes_cmac(key, &sg, 1, mac);
|
||||
}
|
||||
|
||||
static inline bool bt_mesh_s1(const char *m, u8_t salt[16])
|
||||
{
|
||||
const u8_t zero[16] = { 0 };
|
||||
|
||||
return bt_mesh_aes_cmac_one(zero, m, strlen(m), salt);
|
||||
}
|
||||
|
||||
int bt_mesh_k1(const u8_t *ikm, size_t ikm_len, const u8_t salt[16],
|
||||
const char *info, u8_t okm[16]);
|
||||
|
||||
#define bt_mesh_k1_str(ikm, ikm_len, salt_str, info, okm) \
|
||||
({ \
|
||||
const u8_t salt[16] = salt_str; \
|
||||
bt_mesh_k1(ikm, ikm_len, salt, info, okm); \
|
||||
})
|
||||
|
||||
int bt_mesh_k2(const u8_t n[16], const u8_t *p, size_t p_len,
|
||||
u8_t net_id[1], u8_t enc_key[16], u8_t priv_key[16]);
|
||||
|
||||
int bt_mesh_k3(const u8_t n[16], u8_t out[8]);
|
||||
|
||||
int bt_mesh_k4(const u8_t n[16], u8_t out[1]);
|
||||
|
||||
int bt_mesh_id128(const u8_t n[16], const char *s, u8_t out[16]);
|
||||
|
||||
static inline int bt_mesh_id_resolving_key(const u8_t net_key[16],
|
||||
u8_t resolving_key[16])
|
||||
{
|
||||
return bt_mesh_k1_str(net_key, 16, "smbt", "smbi", resolving_key);
|
||||
}
|
||||
|
||||
static inline int bt_mesh_identity_key(const u8_t net_key[16],
|
||||
u8_t identity_key[16])
|
||||
{
|
||||
return bt_mesh_id128(net_key, "nkik", identity_key);
|
||||
}
|
||||
|
||||
static inline int bt_mesh_beacon_key(const u8_t net_key[16],
|
||||
u8_t beacon_key[16])
|
||||
{
|
||||
return bt_mesh_id128(net_key, "nkbk", beacon_key);
|
||||
}
|
||||
|
||||
int bt_mesh_beacon_auth(const u8_t beacon_key[16], u8_t flags,
|
||||
const u8_t net_id[16], u32_t iv_index,
|
||||
u8_t auth[8]);
|
||||
|
||||
static inline int bt_mesh_app_id(const u8_t app_key[16], u8_t app_id[1])
|
||||
{
|
||||
return bt_mesh_k4(app_key, app_id);
|
||||
}
|
||||
|
||||
static inline int bt_mesh_session_key(const u8_t dhkey[32],
|
||||
const u8_t prov_salt[16],
|
||||
u8_t session_key[16])
|
||||
{
|
||||
return bt_mesh_k1(dhkey, 32, prov_salt, "prsk", session_key);
|
||||
}
|
||||
|
||||
static inline int bt_mesh_prov_nonce(const u8_t dhkey[32],
|
||||
const u8_t prov_salt[16],
|
||||
u8_t nonce[13])
|
||||
{
|
||||
u8_t tmp[16];
|
||||
int err;
|
||||
|
||||
err = bt_mesh_k1(dhkey, 32, prov_salt, "prsn", tmp);
|
||||
if (!err) {
|
||||
memcpy(nonce, tmp + 3, 13);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static inline int bt_mesh_dev_key(const u8_t dhkey[32],
|
||||
const u8_t prov_salt[16],
|
||||
u8_t dev_key[16])
|
||||
{
|
||||
return bt_mesh_k1(dhkey, 32, prov_salt, "prdk", dev_key);
|
||||
}
|
||||
|
||||
static inline int bt_mesh_prov_salt(const u8_t conf_salt[16],
|
||||
const u8_t prov_rand[16],
|
||||
const u8_t dev_rand[16],
|
||||
u8_t prov_salt[16])
|
||||
{
|
||||
const u8_t prov_salt_key[16] = { 0 };
|
||||
struct bt_mesh_sg sg[] = {
|
||||
{ conf_salt, 16 },
|
||||
{ prov_rand, 16 },
|
||||
{ dev_rand, 16 },
|
||||
};
|
||||
|
||||
return bt_mesh_aes_cmac(prov_salt_key, sg, ARRAY_SIZE(sg), prov_salt);
|
||||
}
|
||||
|
||||
int bt_mesh_net_obfuscate(u8_t *pdu, u32_t iv_index,
|
||||
const u8_t privacy_key[16]);
|
||||
|
||||
int bt_mesh_net_encrypt(const u8_t key[16], struct net_buf_simple *buf,
|
||||
u32_t iv_index, bool proxy);
|
||||
|
||||
int bt_mesh_net_decrypt(const u8_t key[16], struct net_buf_simple *buf,
|
||||
u32_t iv_index, bool proxy);
|
||||
|
||||
int bt_mesh_app_encrypt(const u8_t key[16], bool dev_key, u8_t aszmic,
|
||||
struct net_buf_simple *buf, const u8_t *ad,
|
||||
u16_t src, u16_t dst, u32_t seq_num, u32_t iv_index);
|
||||
|
||||
int bt_mesh_app_decrypt(const u8_t key[16], bool dev_key, u8_t aszmic,
|
||||
struct net_buf_simple *buf, struct net_buf_simple *out,
|
||||
const u8_t *ad, u16_t src, u16_t dst, u32_t seq_num,
|
||||
u32_t iv_index);
|
||||
|
||||
u8_t bt_mesh_fcs_calc(const u8_t *data, u8_t data_len);
|
||||
|
||||
bool bt_mesh_fcs_check(struct net_buf_simple *buf, u8_t received_fcs);
|
||||
|
||||
int bt_mesh_virtual_addr(const u8_t virtual_label[16], u16_t *addr);
|
||||
|
||||
int bt_mesh_prov_conf_salt(const u8_t conf_inputs[145], u8_t salt[16]);
|
||||
|
||||
int bt_mesh_prov_conf_key(const u8_t dhkey[32], const u8_t conf_salt[16],
|
||||
u8_t conf_key[16]);
|
||||
|
||||
int bt_mesh_prov_conf(const u8_t conf_key[16], const u8_t rand[16],
|
||||
const u8_t auth[16], u8_t conf[16]);
|
||||
|
||||
int bt_mesh_prov_decrypt(const u8_t key[16], u8_t nonce[13],
|
||||
const u8_t data[25 + 8], u8_t out[25]);
|
||||
152
Living_SDK/kernel/protocols/bluetooth/host/bt_mesh/foundation.h
Normal file
152
Living_SDK/kernel/protocols/bluetooth/host/bt_mesh/foundation.h
Normal file
|
|
@ -0,0 +1,152 @@
|
|||
/* Bluetooth Mesh */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2017 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#define OP_APP_KEY_ADD BT_MESH_MODEL_OP_1(0x00)
|
||||
#define OP_APP_KEY_UPDATE BT_MESH_MODEL_OP_1(0x01)
|
||||
#define OP_DEV_COMP_DATA_STATUS BT_MESH_MODEL_OP_1(0x02)
|
||||
#define OP_MOD_PUB_SET BT_MESH_MODEL_OP_1(0x03)
|
||||
#define OP_HEALTH_CURRENT_STATUS BT_MESH_MODEL_OP_1(0x04)
|
||||
#define OP_HEALTH_FAULT_STATUS BT_MESH_MODEL_OP_1(0x05)
|
||||
#define OP_HEARTBEAT_PUB_STATUS BT_MESH_MODEL_OP_1(0x06)
|
||||
#define OP_APP_KEY_DEL BT_MESH_MODEL_OP_2(0x80, 0x00)
|
||||
#define OP_APP_KEY_GET BT_MESH_MODEL_OP_2(0x80, 0x01)
|
||||
#define OP_APP_KEY_LIST BT_MESH_MODEL_OP_2(0x80, 0x02)
|
||||
#define OP_APP_KEY_STATUS BT_MESH_MODEL_OP_2(0x80, 0x03)
|
||||
#define OP_ATTENTION_GET BT_MESH_MODEL_OP_2(0x80, 0x04)
|
||||
#define OP_ATTENTION_SET BT_MESH_MODEL_OP_2(0x80, 0x05)
|
||||
#define OP_ATTENTION_SET_UNREL BT_MESH_MODEL_OP_2(0x80, 0x06)
|
||||
#define OP_ATTENTION_STATUS BT_MESH_MODEL_OP_2(0x80, 0x07)
|
||||
#define OP_DEV_COMP_DATA_GET BT_MESH_MODEL_OP_2(0x80, 0x08)
|
||||
#define OP_BEACON_GET BT_MESH_MODEL_OP_2(0x80, 0x09)
|
||||
#define OP_BEACON_SET BT_MESH_MODEL_OP_2(0x80, 0x0a)
|
||||
#define OP_BEACON_STATUS BT_MESH_MODEL_OP_2(0x80, 0x0b)
|
||||
#define OP_DEFAULT_TTL_GET BT_MESH_MODEL_OP_2(0x80, 0x0c)
|
||||
#define OP_DEFAULT_TTL_SET BT_MESH_MODEL_OP_2(0x80, 0x0d)
|
||||
#define OP_DEFAULT_TTL_STATUS BT_MESH_MODEL_OP_2(0x80, 0x0e)
|
||||
#define OP_FRIEND_GET BT_MESH_MODEL_OP_2(0x80, 0x0f)
|
||||
#define OP_FRIEND_SET BT_MESH_MODEL_OP_2(0x80, 0x10)
|
||||
#define OP_FRIEND_STATUS BT_MESH_MODEL_OP_2(0x80, 0x11)
|
||||
#define OP_GATT_PROXY_GET BT_MESH_MODEL_OP_2(0x80, 0x12)
|
||||
#define OP_GATT_PROXY_SET BT_MESH_MODEL_OP_2(0x80, 0x13)
|
||||
#define OP_GATT_PROXY_STATUS BT_MESH_MODEL_OP_2(0x80, 0x14)
|
||||
#define OP_KRP_GET BT_MESH_MODEL_OP_2(0x80, 0x15)
|
||||
#define OP_KRP_SET BT_MESH_MODEL_OP_2(0x80, 0x16)
|
||||
#define OP_KRP_STATUS BT_MESH_MODEL_OP_2(0x80, 0x17)
|
||||
#define OP_MOD_PUB_GET BT_MESH_MODEL_OP_2(0x80, 0x18)
|
||||
#define OP_MOD_PUB_STATUS BT_MESH_MODEL_OP_2(0x80, 0x19)
|
||||
#define OP_MOD_PUB_VA_SET BT_MESH_MODEL_OP_2(0x80, 0x1a)
|
||||
#define OP_MOD_SUB_ADD BT_MESH_MODEL_OP_2(0x80, 0x1b)
|
||||
#define OP_MOD_SUB_DEL BT_MESH_MODEL_OP_2(0x80, 0x1c)
|
||||
#define OP_MOD_SUB_DEL_ALL BT_MESH_MODEL_OP_2(0x80, 0x1d)
|
||||
#define OP_MOD_SUB_OVERWRITE BT_MESH_MODEL_OP_2(0x80, 0x1e)
|
||||
#define OP_MOD_SUB_STATUS BT_MESH_MODEL_OP_2(0x80, 0x1f)
|
||||
#define OP_MOD_SUB_VA_ADD BT_MESH_MODEL_OP_2(0x80, 0x20)
|
||||
#define OP_MOD_SUB_VA_DEL BT_MESH_MODEL_OP_2(0x80, 0x21)
|
||||
#define OP_MOD_SUB_VA_OVERWRITE BT_MESH_MODEL_OP_2(0x80, 0x22)
|
||||
#define OP_NET_TRANSMIT_GET BT_MESH_MODEL_OP_2(0x80, 0x23)
|
||||
#define OP_NET_TRANSMIT_SET BT_MESH_MODEL_OP_2(0x80, 0x24)
|
||||
#define OP_NET_TRANSMIT_STATUS BT_MESH_MODEL_OP_2(0x80, 0x25)
|
||||
#define OP_RELAY_GET BT_MESH_MODEL_OP_2(0x80, 0x26)
|
||||
#define OP_RELAY_SET BT_MESH_MODEL_OP_2(0x80, 0x27)
|
||||
#define OP_RELAY_STATUS BT_MESH_MODEL_OP_2(0x80, 0x28)
|
||||
#define OP_MOD_SUB_GET BT_MESH_MODEL_OP_2(0x80, 0x29)
|
||||
#define OP_MOD_SUB_LIST BT_MESH_MODEL_OP_2(0x80, 0x2a)
|
||||
#define OP_MOD_SUB_GET_VND BT_MESH_MODEL_OP_2(0x80, 0x2b)
|
||||
#define OP_MOD_SUB_LIST_VND BT_MESH_MODEL_OP_2(0x80, 0x2c)
|
||||
#define OP_LPN_TIMEOUT_GET BT_MESH_MODEL_OP_2(0x80, 0x2d)
|
||||
#define OP_LPN_TIMEOUT_STATUS BT_MESH_MODEL_OP_2(0x80, 0x2e)
|
||||
#define OP_HEALTH_FAULT_CLEAR BT_MESH_MODEL_OP_2(0x80, 0x2f)
|
||||
#define OP_HEALTH_FAULT_CLEAR_UNREL BT_MESH_MODEL_OP_2(0x80, 0x30)
|
||||
#define OP_HEALTH_FAULT_GET BT_MESH_MODEL_OP_2(0x80, 0x31)
|
||||
#define OP_HEALTH_FAULT_TEST BT_MESH_MODEL_OP_2(0x80, 0x32)
|
||||
#define OP_HEALTH_FAULT_TEST_UNREL BT_MESH_MODEL_OP_2(0x80, 0x33)
|
||||
#define OP_HEALTH_PERIOD_GET BT_MESH_MODEL_OP_2(0x80, 0x34)
|
||||
#define OP_HEALTH_PERIOD_SET BT_MESH_MODEL_OP_2(0x80, 0x35)
|
||||
#define OP_HEALTH_PERIOD_SET_UNREL BT_MESH_MODEL_OP_2(0x80, 0x36)
|
||||
#define OP_HEALTH_PERIOD_STATUS BT_MESH_MODEL_OP_2(0x80, 0x37)
|
||||
#define OP_HEARTBEAT_PUB_GET BT_MESH_MODEL_OP_2(0x80, 0x38)
|
||||
#define OP_HEARTBEAT_PUB_SET BT_MESH_MODEL_OP_2(0x80, 0x39)
|
||||
#define OP_HEARTBEAT_SUB_GET BT_MESH_MODEL_OP_2(0x80, 0x3a)
|
||||
#define OP_HEARTBEAT_SUB_SET BT_MESH_MODEL_OP_2(0x80, 0x3b)
|
||||
#define OP_HEARTBEAT_SUB_STATUS BT_MESH_MODEL_OP_2(0x80, 0x3c)
|
||||
#define OP_MOD_APP_BIND BT_MESH_MODEL_OP_2(0x80, 0x3d)
|
||||
#define OP_MOD_APP_STATUS BT_MESH_MODEL_OP_2(0x80, 0x3e)
|
||||
#define OP_MOD_APP_UNBIND BT_MESH_MODEL_OP_2(0x80, 0x3f)
|
||||
#define OP_NET_KEY_ADD BT_MESH_MODEL_OP_2(0x80, 0x40)
|
||||
#define OP_NET_KEY_DEL BT_MESH_MODEL_OP_2(0x80, 0x41)
|
||||
#define OP_NET_KEY_GET BT_MESH_MODEL_OP_2(0x80, 0x42)
|
||||
#define OP_NET_KEY_LIST BT_MESH_MODEL_OP_2(0x80, 0x43)
|
||||
#define OP_NET_KEY_STATUS BT_MESH_MODEL_OP_2(0x80, 0x44)
|
||||
#define OP_NET_KEY_UPDATE BT_MESH_MODEL_OP_2(0x80, 0x45)
|
||||
#define OP_NODE_IDENTITY_GET BT_MESH_MODEL_OP_2(0x80, 0x46)
|
||||
#define OP_NODE_IDENTITY_SET BT_MESH_MODEL_OP_2(0x80, 0x47)
|
||||
#define OP_NODE_IDENTITY_STATUS BT_MESH_MODEL_OP_2(0x80, 0x48)
|
||||
#define OP_NODE_RESET BT_MESH_MODEL_OP_2(0x80, 0x49)
|
||||
#define OP_NODE_RESET_STATUS BT_MESH_MODEL_OP_2(0x80, 0x4a)
|
||||
#define OP_SIG_MOD_APP_GET BT_MESH_MODEL_OP_2(0x80, 0x4b)
|
||||
#define OP_SIG_MOD_APP_LIST BT_MESH_MODEL_OP_2(0x80, 0x4c)
|
||||
#define OP_VND_MOD_APP_GET BT_MESH_MODEL_OP_2(0x80, 0x4d)
|
||||
#define OP_VND_MOD_APP_LIST BT_MESH_MODEL_OP_2(0x80, 0x4e)
|
||||
|
||||
#define STATUS_SUCCESS 0x00
|
||||
#define STATUS_INVALID_ADDRESS 0x01
|
||||
#define STATUS_INVALID_MODEL 0x02
|
||||
#define STATUS_INVALID_APPKEY 0x03
|
||||
#define STATUS_INVALID_NETKEY 0x04
|
||||
#define STATUS_INSUFF_RESOURCES 0x05
|
||||
#define STATUS_IDX_ALREADY_STORED 0x06
|
||||
#define STATUS_NVAL_PUB_PARAM 0x07
|
||||
#define STATUS_NOT_SUB_MOD 0x08
|
||||
#define STATUS_STORAGE_FAIL 0x09
|
||||
#define STATUS_FEAT_NOT_SUPP 0x0a
|
||||
#define STATUS_CANNOT_UPDATE 0x0b
|
||||
#define STATUS_CANNOT_REMOVE 0x0c
|
||||
#define STATUS_CANNOT_BIND 0x0d
|
||||
#define STATUS_TEMP_STATE_CHG_FAIL 0x0e
|
||||
#define STATUS_CANNOT_SET 0x0f
|
||||
#define STATUS_UNSPECIFIED 0x10
|
||||
#define STATUS_INVALID_BINDING 0x11
|
||||
|
||||
int bt_mesh_cfg_srv_init(struct bt_mesh_model *model, bool primary);
|
||||
int bt_mesh_health_srv_init(struct bt_mesh_model *model, bool primary);
|
||||
|
||||
int bt_mesh_cfg_cli_init(struct bt_mesh_model *model, bool primary);
|
||||
int bt_mesh_health_cli_init(struct bt_mesh_model *model, bool primary);
|
||||
|
||||
void bt_mesh_cfg_reset(void);
|
||||
|
||||
void bt_mesh_heartbeat(u16_t src, u16_t dst, u8_t hops, u16_t feat);
|
||||
|
||||
void bt_mesh_attention(struct bt_mesh_model *model, u8_t time);
|
||||
|
||||
u8_t *bt_mesh_label_uuid_get(u16_t addr);
|
||||
|
||||
u8_t bt_mesh_net_transmit_get(void);
|
||||
u8_t bt_mesh_relay_get(void);
|
||||
u8_t bt_mesh_friend_get(void);
|
||||
u8_t bt_mesh_relay_retransmit_get(void);
|
||||
u8_t bt_mesh_beacon_get(void);
|
||||
u8_t bt_mesh_gatt_proxy_get(void);
|
||||
u8_t bt_mesh_default_ttl_get(void);
|
||||
|
||||
#include <misc/byteorder.h>
|
||||
|
||||
static inline void key_idx_pack(struct net_buf_simple *buf,
|
||||
u16_t idx1, u16_t idx2)
|
||||
{
|
||||
net_buf_simple_add_le16(buf, idx1 | ((idx2 & 0x00f) << 12));
|
||||
net_buf_simple_add_u8(buf, idx2 >> 4);
|
||||
}
|
||||
|
||||
static inline void key_idx_unpack(struct net_buf_simple *buf,
|
||||
u16_t *idx1, u16_t *idx2)
|
||||
{
|
||||
*idx1 = sys_get_le16(&buf->data[0]) & 0xfff;
|
||||
*idx2 = sys_get_le16(&buf->data[1]) >> 4;
|
||||
net_buf_simple_pull(buf, 3);
|
||||
}
|
||||
1311
Living_SDK/kernel/protocols/bluetooth/host/bt_mesh/friend.c
Normal file
1311
Living_SDK/kernel/protocols/bluetooth/host/bt_mesh/friend.c
Normal file
File diff suppressed because it is too large
Load diff
44
Living_SDK/kernel/protocols/bluetooth/host/bt_mesh/friend.h
Normal file
44
Living_SDK/kernel/protocols/bluetooth/host/bt_mesh/friend.h
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
/* Bluetooth Mesh */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2017 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
enum bt_mesh_friend_pdu_type {
|
||||
BT_MESH_FRIEND_PDU_SINGLE,
|
||||
BT_MESH_FRIEND_PDU_PARTIAL,
|
||||
BT_MESH_FRIEND_PDU_COMPLETE,
|
||||
};
|
||||
|
||||
bool bt_mesh_friend_match(u16_t net_idx, u16_t addr);
|
||||
|
||||
struct bt_mesh_friend *bt_mesh_friend_find(u16_t net_idx, u16_t lpn_addr,
|
||||
bool valid, bool established);
|
||||
|
||||
void bt_mesh_friend_enqueue_rx(struct bt_mesh_net_rx *rx,
|
||||
enum bt_mesh_friend_pdu_type type,
|
||||
u64_t *seq_auth, struct net_buf_simple *sbuf);
|
||||
bool bt_mesh_friend_enqueue_tx(struct bt_mesh_net_tx *tx,
|
||||
enum bt_mesh_friend_pdu_type type,
|
||||
u64_t *seq_auth, struct net_buf_simple *sbuf);
|
||||
|
||||
void bt_mesh_friend_clear_incomplete(struct bt_mesh_subnet *sub, u16_t src,
|
||||
u16_t dst, u64_t *seq_auth);
|
||||
|
||||
void bt_mesh_friend_sec_update(u16_t net_idx);
|
||||
|
||||
void bt_mesh_friend_clear_net_idx(u16_t net_idx);
|
||||
|
||||
int bt_mesh_friend_poll(struct bt_mesh_net_rx *rx, struct net_buf_simple *buf);
|
||||
int bt_mesh_friend_req(struct bt_mesh_net_rx *rx, struct net_buf_simple *buf);
|
||||
int bt_mesh_friend_clear(struct bt_mesh_net_rx *rx, struct net_buf_simple *buf);
|
||||
int bt_mesh_friend_clear_cfm(struct bt_mesh_net_rx *rx,
|
||||
struct net_buf_simple *buf);
|
||||
int bt_mesh_friend_sub_add(struct bt_mesh_net_rx *rx,
|
||||
struct net_buf_simple *buf);
|
||||
int bt_mesh_friend_sub_rem(struct bt_mesh_net_rx *rx,
|
||||
struct net_buf_simple *buf);
|
||||
|
||||
int bt_mesh_friend_init(void);
|
||||
515
Living_SDK/kernel/protocols/bluetooth/host/bt_mesh/health_cli.c
Normal file
515
Living_SDK/kernel/protocols/bluetooth/host/bt_mesh/health_cli.c
Normal file
|
|
@ -0,0 +1,515 @@
|
|||
/* Bluetooth Mesh */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2017 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <zephyr.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <stdbool.h>
|
||||
#include <zephyr/types.h>
|
||||
#include <misc/util.h>
|
||||
#include <misc/byteorder.h>
|
||||
|
||||
#include <bluetooth/bluetooth.h>
|
||||
#include <bluetooth/conn.h>
|
||||
#include <bluetooth/mesh.h>
|
||||
|
||||
#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_MESH_DEBUG_MODEL)
|
||||
#include "common/log.h"
|
||||
|
||||
#include "foundation.h"
|
||||
|
||||
static s32_t msg_timeout = K_SECONDS(2);
|
||||
|
||||
static struct bt_mesh_health_cli *health_cli;
|
||||
|
||||
struct health_fault_param {
|
||||
u16_t cid;
|
||||
u8_t *expect_test_id;
|
||||
u8_t *test_id;
|
||||
u8_t *faults;
|
||||
size_t *fault_count;
|
||||
};
|
||||
|
||||
static void health_fault_status(struct bt_mesh_model *model,
|
||||
struct bt_mesh_msg_ctx *ctx,
|
||||
struct net_buf_simple *buf)
|
||||
{
|
||||
struct health_fault_param *param;
|
||||
u8_t test_id;
|
||||
u16_t cid;
|
||||
|
||||
BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s",
|
||||
ctx->net_idx, ctx->app_idx, ctx->addr, buf->len,
|
||||
bt_hex(buf->data, buf->len));
|
||||
|
||||
if (health_cli->op_pending != OP_HEALTH_FAULT_STATUS) {
|
||||
BT_WARN("Unexpected Health Fault Status message");
|
||||
return;
|
||||
}
|
||||
|
||||
param = health_cli->op_param;
|
||||
|
||||
test_id = net_buf_simple_pull_u8(buf);
|
||||
if (param->expect_test_id && test_id != *param->expect_test_id) {
|
||||
BT_WARN("Health fault with unexpected Test ID");
|
||||
return;
|
||||
}
|
||||
|
||||
cid = net_buf_simple_pull_le16(buf);
|
||||
if (cid != param->cid) {
|
||||
BT_WARN("Health fault with unexpected Company ID");
|
||||
return;
|
||||
}
|
||||
|
||||
if (param->test_id) {
|
||||
*param->test_id = test_id;
|
||||
}
|
||||
|
||||
if (buf->len > *param->fault_count) {
|
||||
BT_WARN("Got more faults than there's space for");
|
||||
} else {
|
||||
*param->fault_count = buf->len;
|
||||
}
|
||||
|
||||
memcpy(param->faults, buf->data, *param->fault_count);
|
||||
|
||||
k_sem_give(&health_cli->op_sync);
|
||||
}
|
||||
|
||||
static void health_current_status(struct bt_mesh_model *model,
|
||||
struct bt_mesh_msg_ctx *ctx,
|
||||
struct net_buf_simple *buf)
|
||||
{
|
||||
struct bt_mesh_health_cli *cli = model->user_data;
|
||||
u8_t test_id;
|
||||
u16_t cid;
|
||||
|
||||
BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s",
|
||||
ctx->net_idx, ctx->app_idx, ctx->addr, buf->len,
|
||||
bt_hex(buf->data, buf->len));
|
||||
|
||||
test_id = net_buf_simple_pull_u8(buf);
|
||||
cid = net_buf_simple_pull_le16(buf);
|
||||
|
||||
BT_DBG("Test ID 0x%02x Company ID 0x%04x Fault Count %u",
|
||||
test_id, cid, buf->len);
|
||||
|
||||
if (!cli->current_status) {
|
||||
BT_WARN("No Current Status callback available");
|
||||
return;
|
||||
}
|
||||
|
||||
cli->current_status(cli, ctx->addr, test_id, cid, buf->data, buf->len);
|
||||
}
|
||||
|
||||
struct health_period_param {
|
||||
u8_t *divisor;
|
||||
};
|
||||
|
||||
static void health_period_status(struct bt_mesh_model *model,
|
||||
struct bt_mesh_msg_ctx *ctx,
|
||||
struct net_buf_simple *buf)
|
||||
{
|
||||
struct health_period_param *param;
|
||||
|
||||
BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s",
|
||||
ctx->net_idx, ctx->app_idx, ctx->addr, buf->len,
|
||||
bt_hex(buf->data, buf->len));
|
||||
|
||||
if (health_cli->op_pending != OP_HEALTH_PERIOD_STATUS) {
|
||||
BT_WARN("Unexpected Health Period Status message");
|
||||
return;
|
||||
}
|
||||
|
||||
param = health_cli->op_param;
|
||||
|
||||
*param->divisor = net_buf_simple_pull_u8(buf);
|
||||
|
||||
k_sem_give(&health_cli->op_sync);
|
||||
}
|
||||
|
||||
struct health_attention_param {
|
||||
u8_t *attention;
|
||||
};
|
||||
|
||||
static void health_attention_status(struct bt_mesh_model *model,
|
||||
struct bt_mesh_msg_ctx *ctx,
|
||||
struct net_buf_simple *buf)
|
||||
{
|
||||
struct health_attention_param *param;
|
||||
|
||||
BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s",
|
||||
ctx->net_idx, ctx->app_idx, ctx->addr, buf->len,
|
||||
bt_hex(buf->data, buf->len));
|
||||
|
||||
if (health_cli->op_pending != OP_ATTENTION_STATUS) {
|
||||
BT_WARN("Unexpected Health Attention Status message");
|
||||
return;
|
||||
}
|
||||
|
||||
param = health_cli->op_param;
|
||||
|
||||
*param->attention = net_buf_simple_pull_u8(buf);
|
||||
|
||||
k_sem_give(&health_cli->op_sync);
|
||||
}
|
||||
|
||||
const struct bt_mesh_model_op bt_mesh_health_cli_op[] = {
|
||||
{ OP_HEALTH_FAULT_STATUS, 3, health_fault_status },
|
||||
{ OP_HEALTH_CURRENT_STATUS, 3, health_current_status },
|
||||
{ OP_HEALTH_PERIOD_STATUS, 1, health_period_status },
|
||||
{ OP_ATTENTION_STATUS, 1, health_attention_status },
|
||||
BT_MESH_MODEL_OP_END,
|
||||
};
|
||||
|
||||
static int check_cli(void)
|
||||
{
|
||||
if (!health_cli) {
|
||||
BT_ERR("No available Health Client context!");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (health_cli->op_pending) {
|
||||
BT_WARN("Another synchronous operation pending");
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cli_wait(void *param, u32_t op)
|
||||
{
|
||||
int err;
|
||||
|
||||
health_cli->op_param = param;
|
||||
health_cli->op_pending = op;
|
||||
|
||||
err = k_sem_take(&health_cli->op_sync, msg_timeout);
|
||||
|
||||
health_cli->op_pending = 0;
|
||||
health_cli->op_param = NULL;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
int bt_mesh_health_attention_get(u16_t net_idx, u16_t addr, u16_t app_idx,
|
||||
u8_t *attention)
|
||||
{
|
||||
struct net_buf_simple *msg = NET_BUF_SIMPLE(2 + 0 + 4);
|
||||
struct bt_mesh_msg_ctx ctx = {
|
||||
.net_idx = net_idx,
|
||||
.app_idx = app_idx,
|
||||
.addr = addr,
|
||||
.send_ttl = BT_MESH_TTL_DEFAULT,
|
||||
};
|
||||
struct health_attention_param param = {
|
||||
.attention = attention,
|
||||
};
|
||||
int err;
|
||||
|
||||
err = check_cli();
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
bt_mesh_model_msg_init(msg, OP_ATTENTION_GET);
|
||||
|
||||
err = bt_mesh_model_send(health_cli->model, &ctx, msg, NULL, NULL);
|
||||
if (err) {
|
||||
BT_ERR("model_send() failed (err %d)", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
return cli_wait(¶m, OP_ATTENTION_STATUS);
|
||||
}
|
||||
|
||||
int bt_mesh_health_attention_set(u16_t net_idx, u16_t addr, u16_t app_idx,
|
||||
u8_t attention, u8_t *updated_attention)
|
||||
{
|
||||
struct net_buf_simple *msg = NET_BUF_SIMPLE(2 + 1 + 4);
|
||||
struct bt_mesh_msg_ctx ctx = {
|
||||
.net_idx = net_idx,
|
||||
.app_idx = app_idx,
|
||||
.addr = addr,
|
||||
.send_ttl = BT_MESH_TTL_DEFAULT,
|
||||
};
|
||||
struct health_attention_param param = {
|
||||
.attention = updated_attention,
|
||||
};
|
||||
int err;
|
||||
|
||||
err = check_cli();
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
if (updated_attention) {
|
||||
bt_mesh_model_msg_init(msg, OP_ATTENTION_SET);
|
||||
} else {
|
||||
bt_mesh_model_msg_init(msg, OP_ATTENTION_SET_UNREL);
|
||||
}
|
||||
|
||||
net_buf_simple_add_u8(msg, attention);
|
||||
|
||||
err = bt_mesh_model_send(health_cli->model, &ctx, msg, NULL, NULL);
|
||||
if (err) {
|
||||
BT_ERR("model_send() failed (err %d)", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
if (!updated_attention) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return cli_wait(¶m, OP_ATTENTION_STATUS);
|
||||
}
|
||||
|
||||
int bt_mesh_health_period_get(u16_t net_idx, u16_t addr, u16_t app_idx,
|
||||
u8_t *divisor)
|
||||
{
|
||||
struct net_buf_simple *msg = NET_BUF_SIMPLE(2 + 0 + 4);
|
||||
struct bt_mesh_msg_ctx ctx = {
|
||||
.net_idx = net_idx,
|
||||
.app_idx = app_idx,
|
||||
.addr = addr,
|
||||
.send_ttl = BT_MESH_TTL_DEFAULT,
|
||||
};
|
||||
struct health_period_param param = {
|
||||
.divisor = divisor,
|
||||
};
|
||||
int err;
|
||||
|
||||
err = check_cli();
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
bt_mesh_model_msg_init(msg, OP_HEALTH_PERIOD_GET);
|
||||
|
||||
err = bt_mesh_model_send(health_cli->model, &ctx, msg, NULL, NULL);
|
||||
if (err) {
|
||||
BT_ERR("model_send() failed (err %d)", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
return cli_wait(¶m, OP_HEALTH_PERIOD_STATUS);
|
||||
}
|
||||
|
||||
int bt_mesh_health_period_set(u16_t net_idx, u16_t addr, u16_t app_idx,
|
||||
u8_t divisor, u8_t *updated_divisor)
|
||||
{
|
||||
struct net_buf_simple *msg = NET_BUF_SIMPLE(2 + 1 + 4);
|
||||
struct bt_mesh_msg_ctx ctx = {
|
||||
.net_idx = net_idx,
|
||||
.app_idx = app_idx,
|
||||
.addr = addr,
|
||||
.send_ttl = BT_MESH_TTL_DEFAULT,
|
||||
};
|
||||
struct health_period_param param = {
|
||||
.divisor = updated_divisor,
|
||||
};
|
||||
int err;
|
||||
|
||||
err = check_cli();
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
if (updated_divisor) {
|
||||
bt_mesh_model_msg_init(msg, OP_HEALTH_PERIOD_SET);
|
||||
} else {
|
||||
bt_mesh_model_msg_init(msg, OP_HEALTH_PERIOD_SET_UNREL);
|
||||
}
|
||||
|
||||
net_buf_simple_add_u8(msg, divisor);
|
||||
|
||||
err = bt_mesh_model_send(health_cli->model, &ctx, msg, NULL, NULL);
|
||||
if (err) {
|
||||
BT_ERR("model_send() failed (err %d)", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
if (!updated_divisor) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return cli_wait(¶m, OP_HEALTH_PERIOD_STATUS);
|
||||
}
|
||||
|
||||
int bt_mesh_health_fault_test(u16_t net_idx, u16_t addr, u16_t app_idx,
|
||||
u16_t cid, u8_t test_id, u8_t *faults,
|
||||
size_t *fault_count)
|
||||
{
|
||||
struct net_buf_simple *msg = NET_BUF_SIMPLE(2 + 3 + 4);
|
||||
struct bt_mesh_msg_ctx ctx = {
|
||||
.net_idx = net_idx,
|
||||
.app_idx = app_idx,
|
||||
.addr = addr,
|
||||
.send_ttl = BT_MESH_TTL_DEFAULT,
|
||||
};
|
||||
struct health_fault_param param = {
|
||||
.cid = cid,
|
||||
.expect_test_id = &test_id,
|
||||
.faults = faults,
|
||||
.fault_count = fault_count,
|
||||
};
|
||||
int err;
|
||||
|
||||
err = check_cli();
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
if (faults) {
|
||||
bt_mesh_model_msg_init(msg, OP_HEALTH_FAULT_TEST);
|
||||
} else {
|
||||
bt_mesh_model_msg_init(msg, OP_HEALTH_FAULT_TEST_UNREL);
|
||||
}
|
||||
|
||||
net_buf_simple_add_u8(msg, test_id);
|
||||
net_buf_simple_add_le16(msg, cid);
|
||||
|
||||
err = bt_mesh_model_send(health_cli->model, &ctx, msg, NULL, NULL);
|
||||
if (err) {
|
||||
BT_ERR("model_send() failed (err %d)", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
if (!faults) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return cli_wait(¶m, OP_HEALTH_FAULT_STATUS);
|
||||
}
|
||||
|
||||
int bt_mesh_health_fault_clear(u16_t net_idx, u16_t addr, u16_t app_idx,
|
||||
u16_t cid, u8_t *test_id, u8_t *faults,
|
||||
size_t *fault_count)
|
||||
{
|
||||
struct net_buf_simple *msg = NET_BUF_SIMPLE(2 + 2 + 4);
|
||||
struct bt_mesh_msg_ctx ctx = {
|
||||
.net_idx = net_idx,
|
||||
.app_idx = app_idx,
|
||||
.addr = addr,
|
||||
.send_ttl = BT_MESH_TTL_DEFAULT,
|
||||
};
|
||||
struct health_fault_param param = {
|
||||
.cid = cid,
|
||||
.test_id = test_id,
|
||||
.faults = faults,
|
||||
.fault_count = fault_count,
|
||||
};
|
||||
int err;
|
||||
|
||||
err = check_cli();
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
if (test_id) {
|
||||
bt_mesh_model_msg_init(msg, OP_HEALTH_FAULT_CLEAR);
|
||||
} else {
|
||||
bt_mesh_model_msg_init(msg, OP_HEALTH_FAULT_CLEAR_UNREL);
|
||||
}
|
||||
|
||||
net_buf_simple_add_le16(msg, cid);
|
||||
|
||||
err = bt_mesh_model_send(health_cli->model, &ctx, msg, NULL, NULL);
|
||||
if (err) {
|
||||
BT_ERR("model_send() failed (err %d)", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
if (!test_id) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return cli_wait(¶m, OP_HEALTH_FAULT_STATUS);
|
||||
}
|
||||
|
||||
int bt_mesh_health_fault_get(u16_t net_idx, u16_t addr, u16_t app_idx,
|
||||
u16_t cid, u8_t *test_id, u8_t *faults,
|
||||
size_t *fault_count)
|
||||
{
|
||||
struct net_buf_simple *msg = NET_BUF_SIMPLE(2 + 2 + 4);
|
||||
struct bt_mesh_msg_ctx ctx = {
|
||||
.net_idx = net_idx,
|
||||
.app_idx = app_idx,
|
||||
.addr = addr,
|
||||
.send_ttl = BT_MESH_TTL_DEFAULT,
|
||||
};
|
||||
struct health_fault_param param = {
|
||||
.cid = cid,
|
||||
.test_id = test_id,
|
||||
.faults = faults,
|
||||
.fault_count = fault_count,
|
||||
};
|
||||
int err;
|
||||
|
||||
err = check_cli();
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
bt_mesh_model_msg_init(msg, OP_HEALTH_FAULT_GET);
|
||||
net_buf_simple_add_le16(msg, cid);
|
||||
|
||||
err = bt_mesh_model_send(health_cli->model, &ctx, msg, NULL, NULL);
|
||||
if (err) {
|
||||
BT_ERR("model_send() failed (err %d)", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
return cli_wait(¶m, OP_HEALTH_FAULT_STATUS);
|
||||
}
|
||||
|
||||
s32_t bt_mesh_health_cli_timeout_get(void)
|
||||
{
|
||||
return msg_timeout;
|
||||
}
|
||||
|
||||
void bt_mesh_health_cli_timeout_set(s32_t timeout)
|
||||
{
|
||||
msg_timeout = timeout;
|
||||
}
|
||||
|
||||
int bt_mesh_health_cli_set(struct bt_mesh_model *model)
|
||||
{
|
||||
if (!model->user_data) {
|
||||
BT_ERR("No Health Client context for given model");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
health_cli = model->user_data;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bt_mesh_health_cli_init(struct bt_mesh_model *model, bool primary)
|
||||
{
|
||||
struct bt_mesh_health_cli *cli = model->user_data;
|
||||
|
||||
BT_DBG("primary %u", primary);
|
||||
|
||||
if (!cli) {
|
||||
BT_ERR("No Health Client context provided");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
cli = model->user_data;
|
||||
cli->model = model;
|
||||
|
||||
k_sem_init(&cli->op_sync, 0, 1);
|
||||
|
||||
/* Set the default health client pointer */
|
||||
if (!health_cli) {
|
||||
health_cli = cli;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
435
Living_SDK/kernel/protocols/bluetooth/host/bt_mesh/health_srv.c
Normal file
435
Living_SDK/kernel/protocols/bluetooth/host/bt_mesh/health_srv.c
Normal file
|
|
@ -0,0 +1,435 @@
|
|||
/* Bluetooth Mesh */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2017 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <zephyr.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <stdbool.h>
|
||||
#include <zephyr/types.h>
|
||||
#include <misc/byteorder.h>
|
||||
#include <misc/util.h>
|
||||
|
||||
#include <bluetooth/bluetooth.h>
|
||||
#include <bluetooth/mesh.h>
|
||||
|
||||
#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_MESH_DEBUG_MODEL)
|
||||
#include "common/log.h"
|
||||
|
||||
#include "mesh.h"
|
||||
#include "adv.h"
|
||||
#include "net.h"
|
||||
#include "transport.h"
|
||||
#include "access.h"
|
||||
#include "foundation.h"
|
||||
|
||||
#define HEALTH_TEST_STANDARD 0x00
|
||||
|
||||
/* Health Server context of the primary element */
|
||||
struct bt_mesh_health_srv *health_srv;
|
||||
|
||||
static void health_get_registered(struct bt_mesh_model *mod,
|
||||
u16_t company_id,
|
||||
struct net_buf_simple *msg)
|
||||
{
|
||||
struct bt_mesh_health_srv *srv = mod->user_data;
|
||||
u8_t *test_id;
|
||||
|
||||
BT_DBG("Company ID 0x%04x", company_id);
|
||||
|
||||
bt_mesh_model_msg_init(msg, OP_HEALTH_FAULT_STATUS);
|
||||
|
||||
test_id = net_buf_simple_add(msg, 1);
|
||||
net_buf_simple_add_le16(msg, company_id);
|
||||
|
||||
if (srv->cb && srv->cb->fault_get_reg) {
|
||||
u8_t fault_count = net_buf_simple_tailroom(msg) - 4;
|
||||
int err;
|
||||
|
||||
err = srv->cb->fault_get_reg(mod, company_id, test_id,
|
||||
net_buf_simple_tail(msg),
|
||||
&fault_count);
|
||||
if (err) {
|
||||
BT_ERR("Failed to get faults (err %d)", err);
|
||||
*test_id = HEALTH_TEST_STANDARD;
|
||||
} else {
|
||||
net_buf_simple_add(msg, fault_count);
|
||||
}
|
||||
} else {
|
||||
BT_WARN("No callback for getting faults");
|
||||
*test_id = HEALTH_TEST_STANDARD;
|
||||
}
|
||||
}
|
||||
|
||||
static size_t health_get_current(struct bt_mesh_model *mod,
|
||||
struct net_buf_simple *msg)
|
||||
{
|
||||
struct bt_mesh_health_srv *srv = mod->user_data;
|
||||
const struct bt_mesh_comp *comp;
|
||||
u8_t *test_id, *company_ptr;
|
||||
u16_t company_id;
|
||||
u8_t fault_count;
|
||||
int err;
|
||||
|
||||
bt_mesh_model_msg_init(msg, OP_HEALTH_CURRENT_STATUS);
|
||||
|
||||
test_id = net_buf_simple_add(msg, 1);
|
||||
company_ptr = net_buf_simple_add(msg, sizeof(company_id));
|
||||
comp = bt_mesh_comp_get();
|
||||
|
||||
if (srv->cb && srv->cb->fault_get_cur) {
|
||||
fault_count = net_buf_simple_tailroom(msg);
|
||||
err = srv->cb->fault_get_cur(mod, test_id, &company_id,
|
||||
net_buf_simple_tail(msg),
|
||||
&fault_count);
|
||||
if (err) {
|
||||
BT_ERR("Failed to get faults (err %d)", err);
|
||||
sys_put_le16(comp->cid, company_ptr);
|
||||
*test_id = HEALTH_TEST_STANDARD;
|
||||
fault_count = 0;
|
||||
} else {
|
||||
sys_put_le16(company_id, company_ptr);
|
||||
net_buf_simple_add(msg, fault_count);
|
||||
}
|
||||
} else {
|
||||
BT_WARN("No callback for getting faults");
|
||||
sys_put_le16(comp->cid, company_ptr);
|
||||
*test_id = HEALTH_TEST_STANDARD;
|
||||
fault_count = 0;
|
||||
}
|
||||
|
||||
return fault_count;
|
||||
}
|
||||
|
||||
static void health_fault_get(struct bt_mesh_model *model,
|
||||
struct bt_mesh_msg_ctx *ctx,
|
||||
struct net_buf_simple *buf)
|
||||
{
|
||||
struct net_buf_simple *sdu = NET_BUF_SIMPLE(BT_MESH_TX_SDU_MAX);
|
||||
u16_t company_id;
|
||||
|
||||
company_id = net_buf_simple_pull_le16(buf);
|
||||
|
||||
BT_DBG("company_id 0x%04x", company_id);
|
||||
|
||||
health_get_registered(model, company_id, sdu);
|
||||
|
||||
if (bt_mesh_model_send(model, ctx, sdu, NULL, NULL)) {
|
||||
BT_ERR("Unable to send Health Current Status response");
|
||||
}
|
||||
}
|
||||
|
||||
static void health_fault_clear_unrel(struct bt_mesh_model *model,
|
||||
struct bt_mesh_msg_ctx *ctx,
|
||||
struct net_buf_simple *buf)
|
||||
{
|
||||
struct bt_mesh_health_srv *srv = model->user_data;
|
||||
u16_t company_id;
|
||||
|
||||
company_id = net_buf_simple_pull_le16(buf);
|
||||
|
||||
BT_DBG("company_id 0x%04x", company_id);
|
||||
|
||||
if (srv->cb && srv->cb->fault_clear) {
|
||||
srv->cb->fault_clear(model, company_id);
|
||||
}
|
||||
}
|
||||
|
||||
static void health_fault_clear(struct bt_mesh_model *model,
|
||||
struct bt_mesh_msg_ctx *ctx,
|
||||
struct net_buf_simple *buf)
|
||||
{
|
||||
struct net_buf_simple *sdu = NET_BUF_SIMPLE(BT_MESH_TX_SDU_MAX);
|
||||
struct bt_mesh_health_srv *srv = model->user_data;
|
||||
u16_t company_id;
|
||||
|
||||
company_id = net_buf_simple_pull_le16(buf);
|
||||
|
||||
BT_DBG("company_id 0x%04x", company_id);
|
||||
|
||||
if (srv->cb && srv->cb->fault_clear) {
|
||||
srv->cb->fault_clear(model, company_id);
|
||||
}
|
||||
|
||||
health_get_registered(model, company_id, sdu);
|
||||
|
||||
if (bt_mesh_model_send(model, ctx, sdu, NULL, NULL)) {
|
||||
BT_ERR("Unable to send Health Current Status response");
|
||||
}
|
||||
}
|
||||
|
||||
static void health_fault_test_unrel(struct bt_mesh_model *model,
|
||||
struct bt_mesh_msg_ctx *ctx,
|
||||
struct net_buf_simple *buf)
|
||||
{
|
||||
struct bt_mesh_health_srv *srv = model->user_data;
|
||||
u16_t company_id;
|
||||
u8_t test_id;
|
||||
|
||||
test_id = net_buf_simple_pull_u8(buf);
|
||||
company_id = net_buf_simple_pull_le16(buf);
|
||||
|
||||
BT_DBG("test 0x%02x company 0x%04x", test_id, company_id);
|
||||
|
||||
if (srv->cb && srv->cb->fault_test) {
|
||||
srv->cb->fault_test(model, test_id, company_id);
|
||||
}
|
||||
}
|
||||
|
||||
static void health_fault_test(struct bt_mesh_model *model,
|
||||
struct bt_mesh_msg_ctx *ctx,
|
||||
struct net_buf_simple *buf)
|
||||
{
|
||||
struct net_buf_simple *sdu = NET_BUF_SIMPLE(BT_MESH_TX_SDU_MAX);
|
||||
struct bt_mesh_health_srv *srv = model->user_data;
|
||||
u16_t company_id;
|
||||
u8_t test_id;
|
||||
|
||||
BT_DBG("");
|
||||
|
||||
test_id = net_buf_simple_pull_u8(buf);
|
||||
company_id = net_buf_simple_pull_le16(buf);
|
||||
|
||||
BT_DBG("test 0x%02x company 0x%04x", test_id, company_id);
|
||||
|
||||
if (srv->cb && srv->cb->fault_test) {
|
||||
int err;
|
||||
|
||||
err = srv->cb->fault_test(model, test_id, company_id);
|
||||
if (err) {
|
||||
BT_WARN("Running fault test failed with err %d", err);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
health_get_registered(model, company_id, sdu);
|
||||
|
||||
if (bt_mesh_model_send(model, ctx, sdu, NULL, NULL)) {
|
||||
BT_ERR("Unable to send Health Current Status response");
|
||||
}
|
||||
}
|
||||
|
||||
static void send_attention_status(struct bt_mesh_model *model,
|
||||
struct bt_mesh_msg_ctx *ctx)
|
||||
{
|
||||
/* Needed size: opcode (2 bytes) + msg + MIC */
|
||||
struct net_buf_simple *msg = NET_BUF_SIMPLE(2 + 1 + 4);
|
||||
struct bt_mesh_health_srv *srv = model->user_data;
|
||||
u8_t time;
|
||||
|
||||
time = k_delayed_work_remaining_get(&srv->attn_timer) / 1000;
|
||||
BT_DBG("%u second%s", time, (time == 1) ? "" : "s");
|
||||
|
||||
bt_mesh_model_msg_init(msg, OP_ATTENTION_STATUS);
|
||||
|
||||
net_buf_simple_add_u8(msg, time);
|
||||
|
||||
if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) {
|
||||
BT_ERR("Unable to send Attention Status");
|
||||
}
|
||||
}
|
||||
|
||||
static void attention_get(struct bt_mesh_model *model,
|
||||
struct bt_mesh_msg_ctx *ctx,
|
||||
struct net_buf_simple *buf)
|
||||
{
|
||||
BT_DBG("");
|
||||
|
||||
send_attention_status(model, ctx);
|
||||
}
|
||||
|
||||
static void attention_set_unrel(struct bt_mesh_model *model,
|
||||
struct bt_mesh_msg_ctx *ctx,
|
||||
struct net_buf_simple *buf)
|
||||
{
|
||||
u8_t time;
|
||||
|
||||
time = net_buf_simple_pull_u8(buf);
|
||||
|
||||
BT_DBG("%u second%s", time, (time == 1) ? "" : "s");
|
||||
|
||||
bt_mesh_attention(model, time);
|
||||
}
|
||||
|
||||
static void attention_set(struct bt_mesh_model *model,
|
||||
struct bt_mesh_msg_ctx *ctx,
|
||||
struct net_buf_simple *buf)
|
||||
{
|
||||
BT_DBG("");
|
||||
|
||||
attention_set_unrel(model, ctx, buf);
|
||||
|
||||
send_attention_status(model, ctx);
|
||||
}
|
||||
|
||||
static void send_health_period_status(struct bt_mesh_model *model,
|
||||
struct bt_mesh_msg_ctx *ctx)
|
||||
{
|
||||
/* Needed size: opcode (2 bytes) + msg + MIC */
|
||||
struct net_buf_simple *msg = NET_BUF_SIMPLE(2 + 1 + 4);
|
||||
|
||||
bt_mesh_model_msg_init(msg, OP_HEALTH_PERIOD_STATUS);
|
||||
|
||||
net_buf_simple_add_u8(msg, model->pub->period_div);
|
||||
|
||||
if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) {
|
||||
BT_ERR("Unable to send Health Period Status");
|
||||
}
|
||||
}
|
||||
|
||||
static void health_period_get(struct bt_mesh_model *model,
|
||||
struct bt_mesh_msg_ctx *ctx,
|
||||
struct net_buf_simple *buf)
|
||||
{
|
||||
BT_DBG("");
|
||||
|
||||
send_health_period_status(model, ctx);
|
||||
}
|
||||
|
||||
static void health_period_set_unrel(struct bt_mesh_model *model,
|
||||
struct bt_mesh_msg_ctx *ctx,
|
||||
struct net_buf_simple *buf)
|
||||
{
|
||||
u8_t period;
|
||||
|
||||
period = net_buf_simple_pull_u8(buf);
|
||||
if (period > 15) {
|
||||
BT_WARN("Prohibited period value %u", period);
|
||||
return;
|
||||
}
|
||||
|
||||
BT_DBG("period %u", period);
|
||||
|
||||
model->pub->period_div = period;
|
||||
}
|
||||
|
||||
static void health_period_set(struct bt_mesh_model *model,
|
||||
struct bt_mesh_msg_ctx *ctx,
|
||||
struct net_buf_simple *buf)
|
||||
{
|
||||
BT_DBG("");
|
||||
|
||||
health_period_set_unrel(model, ctx, buf);
|
||||
|
||||
send_health_period_status(model, ctx);
|
||||
}
|
||||
|
||||
const struct bt_mesh_model_op bt_mesh_health_srv_op[] = {
|
||||
{ OP_HEALTH_FAULT_GET, 2, health_fault_get },
|
||||
{ OP_HEALTH_FAULT_CLEAR, 2, health_fault_clear },
|
||||
{ OP_HEALTH_FAULT_CLEAR_UNREL, 2, health_fault_clear_unrel },
|
||||
{ OP_HEALTH_FAULT_TEST, 3, health_fault_test },
|
||||
{ OP_HEALTH_FAULT_TEST_UNREL, 3, health_fault_test_unrel },
|
||||
{ OP_HEALTH_PERIOD_GET, 0, health_period_get },
|
||||
{ OP_HEALTH_PERIOD_SET, 1, health_period_set },
|
||||
{ OP_HEALTH_PERIOD_SET_UNREL, 1, health_period_set_unrel },
|
||||
{ OP_ATTENTION_GET, 0, attention_get },
|
||||
{ OP_ATTENTION_SET, 1, attention_set },
|
||||
{ OP_ATTENTION_SET_UNREL, 1, attention_set_unrel },
|
||||
BT_MESH_MODEL_OP_END,
|
||||
};
|
||||
|
||||
static int health_pub_update(struct bt_mesh_model *mod)
|
||||
{
|
||||
struct bt_mesh_model_pub *pub = mod->pub;
|
||||
size_t count;
|
||||
|
||||
BT_DBG("");
|
||||
|
||||
count = health_get_current(mod, pub->msg);
|
||||
if (!count) {
|
||||
pub->period_div = 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bt_mesh_fault_update(struct bt_mesh_elem *elem)
|
||||
{
|
||||
struct bt_mesh_model *mod;
|
||||
|
||||
mod = bt_mesh_model_find(elem, BT_MESH_MODEL_ID_HEALTH_SRV);
|
||||
if (!mod) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return bt_mesh_model_publish(mod);
|
||||
}
|
||||
|
||||
static void attention_off(struct k_work *work)
|
||||
{
|
||||
struct bt_mesh_health_srv *srv = CONTAINER_OF(work,
|
||||
struct bt_mesh_health_srv,
|
||||
attn_timer.work);
|
||||
BT_DBG("");
|
||||
|
||||
if (srv->cb && srv->cb->attn_off) {
|
||||
srv->cb->attn_off(srv->model);
|
||||
}
|
||||
}
|
||||
|
||||
int bt_mesh_health_srv_init(struct bt_mesh_model *model, bool primary)
|
||||
{
|
||||
struct bt_mesh_health_srv *srv = model->user_data;
|
||||
|
||||
if (!srv) {
|
||||
if (!primary) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
BT_ERR("No Health Server context provided");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!model->pub) {
|
||||
BT_ERR("Health Server has no publication support");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
model->pub->update = health_pub_update,
|
||||
|
||||
k_delayed_work_init(&srv->attn_timer, attention_off);
|
||||
|
||||
srv->model = model;
|
||||
|
||||
if (primary) {
|
||||
health_srv = srv;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void bt_mesh_attention(struct bt_mesh_model *model, u8_t time)
|
||||
{
|
||||
struct bt_mesh_health_srv *srv;
|
||||
|
||||
if (!model) {
|
||||
srv = health_srv;
|
||||
if (!srv) {
|
||||
BT_WARN("No Health Server available");
|
||||
return;
|
||||
}
|
||||
|
||||
model = srv->model;
|
||||
} else {
|
||||
srv = model->user_data;
|
||||
}
|
||||
|
||||
if (time) {
|
||||
if (srv->cb && srv->cb->attn_on) {
|
||||
srv->cb->attn_on(model);
|
||||
}
|
||||
|
||||
k_delayed_work_submit(&srv->attn_timer, time * 1000);
|
||||
} else {
|
||||
k_delayed_work_cancel(&srv->attn_timer);
|
||||
|
||||
if (srv->cb && srv->cb->attn_off) {
|
||||
srv->cb->attn_off(model);
|
||||
}
|
||||
}
|
||||
}
|
||||
1045
Living_SDK/kernel/protocols/bluetooth/host/bt_mesh/lpn.c
Normal file
1045
Living_SDK/kernel/protocols/bluetooth/host/bt_mesh/lpn.c
Normal file
File diff suppressed because it is too large
Load diff
62
Living_SDK/kernel/protocols/bluetooth/host/bt_mesh/lpn.h
Normal file
62
Living_SDK/kernel/protocols/bluetooth/host/bt_mesh/lpn.h
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
/* Bluetooth Mesh */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2017 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
int bt_mesh_lpn_friend_update(struct bt_mesh_net_rx *rx,
|
||||
struct net_buf_simple *buf);
|
||||
int bt_mesh_lpn_friend_offer(struct bt_mesh_net_rx *rx,
|
||||
struct net_buf_simple *buf);
|
||||
int bt_mesh_lpn_friend_clear_cfm(struct bt_mesh_net_rx *rx,
|
||||
struct net_buf_simple *buf);
|
||||
int bt_mesh_lpn_friend_sub_cfm(struct bt_mesh_net_rx *rx,
|
||||
struct net_buf_simple *buf);
|
||||
|
||||
static inline bool bt_mesh_lpn_established(void)
|
||||
{
|
||||
#if defined(CONFIG_BT_MESH_LOW_POWER)
|
||||
return bt_mesh.lpn.established;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline bool bt_mesh_lpn_match(u16_t addr)
|
||||
{
|
||||
#if defined(CONFIG_BT_MESH_LOW_POWER)
|
||||
if (bt_mesh_lpn_established()) {
|
||||
return (addr == bt_mesh.lpn.frnd);
|
||||
}
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline bool bt_mesh_lpn_waiting_update(void)
|
||||
{
|
||||
#if defined(CONFIG_BT_MESH_LOW_POWER)
|
||||
return (bt_mesh.lpn.state == BT_MESH_LPN_WAIT_UPDATE);
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline bool bt_mesh_lpn_timer(void)
|
||||
{
|
||||
#if defined(CONFIG_BT_MESH_LPN_AUTO)
|
||||
return (bt_mesh.lpn.state == BT_MESH_LPN_TIMER);
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
void bt_mesh_lpn_msg_received(struct bt_mesh_net_rx *rx);
|
||||
|
||||
void bt_mesh_lpn_group_add(u16_t group);
|
||||
void bt_mesh_lpn_group_del(u16_t *groups, size_t group_count);
|
||||
|
||||
void bt_mesh_lpn_disable(bool force);
|
||||
|
||||
int bt_mesh_lpn_init(void);
|
||||
226
Living_SDK/kernel/protocols/bluetooth/host/bt_mesh/main.c
Normal file
226
Living_SDK/kernel/protocols/bluetooth/host/bt_mesh/main.c
Normal file
|
|
@ -0,0 +1,226 @@
|
|||
/* Bluetooth Mesh */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2017 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <zephyr.h>
|
||||
#include <stdbool.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <net/buf.h>
|
||||
#include <bluetooth/bluetooth.h>
|
||||
#include <bluetooth/conn.h>
|
||||
#include <bluetooth/mesh.h>
|
||||
|
||||
#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_MESH_DEBUG)
|
||||
#include "common/log.h"
|
||||
|
||||
#include "test.h"
|
||||
#include "adv.h"
|
||||
#include "prov.h"
|
||||
#include "net.h"
|
||||
#include "beacon.h"
|
||||
#include "lpn.h"
|
||||
#include "friend.h"
|
||||
#include "transport.h"
|
||||
#include "access.h"
|
||||
#include "foundation.h"
|
||||
#include "proxy.h"
|
||||
#include "mesh.h"
|
||||
|
||||
static bool provisioned;
|
||||
|
||||
int bt_mesh_provision(const u8_t net_key[16], u16_t net_idx,
|
||||
u8_t flags, u32_t iv_index, u32_t seq,
|
||||
u16_t addr, const u8_t dev_key[16])
|
||||
{
|
||||
int err;
|
||||
|
||||
BT_INFO("Primary Element: 0x%04x", addr);
|
||||
BT_DBG("net_idx 0x%04x flags 0x%02x iv_index 0x%04x",
|
||||
net_idx, flags, iv_index);
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_MESH_PB_GATT)) {
|
||||
bt_mesh_proxy_prov_disable();
|
||||
}
|
||||
|
||||
err = bt_mesh_net_create(net_idx, flags, net_key, iv_index);
|
||||
if (err) {
|
||||
if (IS_ENABLED(CONFIG_BT_MESH_PB_GATT)) {
|
||||
bt_mesh_proxy_prov_enable();
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
bt_mesh.seq = seq;
|
||||
|
||||
bt_mesh_comp_provision(addr);
|
||||
|
||||
memcpy(bt_mesh.dev_key, dev_key, 16);
|
||||
|
||||
provisioned = true;
|
||||
|
||||
if (bt_mesh_beacon_get() == BT_MESH_BEACON_ENABLED) {
|
||||
bt_mesh_beacon_enable();
|
||||
} else {
|
||||
bt_mesh_beacon_disable();
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY) &&
|
||||
bt_mesh_gatt_proxy_get() != BT_MESH_GATT_PROXY_NOT_SUPPORTED) {
|
||||
bt_mesh_proxy_gatt_enable();
|
||||
bt_mesh_adv_update();
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_MESH_LOW_POWER)) {
|
||||
bt_mesh_lpn_init();
|
||||
} else {
|
||||
bt_mesh_scan_enable();
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_MESH_FRIEND)) {
|
||||
bt_mesh_friend_init();
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_MESH_PROV)) {
|
||||
bt_mesh_prov_complete(net_idx, addr);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void bt_mesh_reset(void)
|
||||
{
|
||||
if (!provisioned) {
|
||||
return;
|
||||
}
|
||||
|
||||
bt_mesh_comp_unprovision();
|
||||
|
||||
bt_mesh.iv_index = 0;
|
||||
bt_mesh.seq = 0;
|
||||
bt_mesh.iv_update = 0;
|
||||
bt_mesh.pending_update = 0;
|
||||
bt_mesh.valid = 0;
|
||||
bt_mesh.last_update = 0;
|
||||
bt_mesh.ivu_initiator = 0;
|
||||
|
||||
k_delayed_work_cancel(&bt_mesh.ivu_complete);
|
||||
|
||||
bt_mesh_cfg_reset();
|
||||
|
||||
bt_mesh_rx_reset();
|
||||
bt_mesh_tx_reset();
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_MESH_LOW_POWER)) {
|
||||
bt_mesh_lpn_disable(true);
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_MESH_FRIEND)) {
|
||||
bt_mesh_friend_clear_net_idx(BT_MESH_KEY_ANY);
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY)) {
|
||||
bt_mesh_proxy_gatt_disable();
|
||||
}
|
||||
|
||||
memset(bt_mesh.dev_key, 0, sizeof(bt_mesh.dev_key));
|
||||
|
||||
memset(bt_mesh.rpl, 0, sizeof(bt_mesh.rpl));
|
||||
|
||||
provisioned = false;
|
||||
|
||||
bt_mesh_scan_disable();
|
||||
bt_mesh_beacon_disable();
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_MESH_PROV)) {
|
||||
bt_mesh_prov_reset();
|
||||
}
|
||||
}
|
||||
|
||||
bool bt_mesh_is_provisioned(void)
|
||||
{
|
||||
return provisioned;
|
||||
}
|
||||
|
||||
int bt_mesh_prov_enable(bt_mesh_prov_bearer_t bearers)
|
||||
{
|
||||
if (bt_mesh_is_provisioned()) {
|
||||
return -EALREADY;
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_MESH_PB_ADV) &&
|
||||
(bearers & BT_MESH_PROV_ADV)) {
|
||||
/* Make sure we're scanning for provisioning inviations */
|
||||
bt_mesh_scan_enable();
|
||||
/* Enable unprovisioned beacon sending */
|
||||
bt_mesh_beacon_enable();
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_MESH_PB_GATT) &&
|
||||
(bearers & BT_MESH_PROV_GATT)) {
|
||||
bt_mesh_proxy_prov_enable();
|
||||
bt_mesh_adv_update();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bt_mesh_prov_disable(bt_mesh_prov_bearer_t bearers)
|
||||
{
|
||||
if (bt_mesh_is_provisioned()) {
|
||||
return -EALREADY;
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_MESH_PB_ADV) &&
|
||||
(bearers & BT_MESH_PROV_ADV)) {
|
||||
bt_mesh_beacon_disable();
|
||||
bt_mesh_scan_disable();
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_MESH_PB_GATT) &&
|
||||
(bearers & BT_MESH_PROV_GATT)) {
|
||||
bt_mesh_proxy_prov_disable();
|
||||
bt_mesh_adv_update();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bt_mesh_init(const struct bt_mesh_prov *prov,
|
||||
const struct bt_mesh_comp *comp)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = bt_mesh_test();
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
err = bt_mesh_comp_register(comp);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_MESH_PROV)) {
|
||||
err = bt_mesh_prov_init(prov);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
bt_mesh_net_init();
|
||||
bt_mesh_trans_init();
|
||||
bt_mesh_beacon_init();
|
||||
bt_mesh_adv_init();
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_MESH_PROXY)) {
|
||||
bt_mesh_proxy_init();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
19
Living_SDK/kernel/protocols/bluetooth/host/bt_mesh/mesh.h
Normal file
19
Living_SDK/kernel/protocols/bluetooth/host/bt_mesh/mesh.h
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
/* Bluetooth Mesh */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2017 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#define BT_MESH_KEY_PRIMARY 0x0000
|
||||
#define BT_MESH_KEY_ANY 0xffff
|
||||
|
||||
#define BT_MESH_ADDR_IS_UNICAST(addr) ((addr) && (addr) < 0x8000)
|
||||
#define BT_MESH_ADDR_IS_GROUP(addr) ((addr) >= 0xc000 && (addr) <= 0xff00)
|
||||
#define BT_MESH_ADDR_IS_VIRTUAL(addr) ((addr) >= 0x8000 && (addr) < 0xc000)
|
||||
#define BT_MESH_ADDR_IS_RFU(addr) ((addr) >= 0xff00 && (addr) <= 0xfffb)
|
||||
|
||||
struct bt_mesh_net;
|
||||
|
||||
bool bt_mesh_is_provisioned(void);
|
||||
1346
Living_SDK/kernel/protocols/bluetooth/host/bt_mesh/net.c
Normal file
1346
Living_SDK/kernel/protocols/bluetooth/host/bt_mesh/net.c
Normal file
File diff suppressed because it is too large
Load diff
329
Living_SDK/kernel/protocols/bluetooth/host/bt_mesh/net.h
Normal file
329
Living_SDK/kernel/protocols/bluetooth/host/bt_mesh/net.h
Normal file
|
|
@ -0,0 +1,329 @@
|
|||
/* Bluetooth Mesh */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2017 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#define BT_MESH_NET_FLAG_KR BIT(0)
|
||||
#define BT_MESH_NET_FLAG_IVU BIT(1)
|
||||
|
||||
#define BT_MESH_KR_NORMAL 0x00
|
||||
#define BT_MESH_KR_PHASE_1 0x01
|
||||
#define BT_MESH_KR_PHASE_2 0x02
|
||||
#define BT_MESH_KR_PHASE_3 0x03
|
||||
|
||||
#define BT_MESH_IV_UPDATE(flags) ((flags >> 1) & 0x01)
|
||||
#define BT_MESH_KEY_REFRESH(flags) (flags & 0x01)
|
||||
|
||||
struct bt_mesh_app_key {
|
||||
u16_t net_idx;
|
||||
u16_t app_idx;
|
||||
bool updated;
|
||||
struct bt_mesh_app_keys {
|
||||
u8_t id;
|
||||
u8_t val[16];
|
||||
} keys[2];
|
||||
};
|
||||
|
||||
struct bt_mesh_subnet {
|
||||
u32_t beacon_sent; /* Timestamp of last sent beacon */
|
||||
u8_t beacons_last; /* Number of beacons during last
|
||||
* observation window
|
||||
*/
|
||||
u8_t beacons_cur; /* Number of beaconds observed during
|
||||
* currently ongoing window.
|
||||
*/
|
||||
|
||||
u8_t beacon_cache[21]; /* Cached last authenticated beacon */
|
||||
|
||||
u16_t net_idx; /* NetKeyIndex */
|
||||
|
||||
bool kr_flag; /* Key Refresh Flag */
|
||||
u8_t kr_phase; /* Key Refresh Phase */
|
||||
|
||||
u8_t node_id; /* Node Identity State */
|
||||
u32_t node_id_start; /* Node Identity started timestamp */
|
||||
|
||||
u8_t auth[8]; /* Beacon Authentication Value */
|
||||
|
||||
struct bt_mesh_subnet_keys {
|
||||
u8_t net[16]; /* NetKey */
|
||||
u8_t nid; /* NID */
|
||||
u8_t enc[16]; /* EncKey */
|
||||
u8_t net_id[8]; /* Network ID */
|
||||
#if defined(CONFIG_BT_MESH_GATT_PROXY)
|
||||
u8_t identity[16]; /* IdentityKey */
|
||||
#endif
|
||||
u8_t privacy[16]; /* PrivacyKey */
|
||||
u8_t beacon[16]; /* BeaconKey */
|
||||
} keys[2];
|
||||
};
|
||||
|
||||
struct bt_mesh_rpl {
|
||||
u16_t src;
|
||||
bool old_iv;
|
||||
u32_t seq;
|
||||
};
|
||||
|
||||
#if defined(CONFIG_BT_MESH_FRIEND)
|
||||
#define FRIEND_SEG_RX CONFIG_BT_MESH_FRIEND_SEG_RX
|
||||
#define FRIEND_SUB_LIST_SIZE CONFIG_BT_MESH_FRIEND_SUB_LIST_SIZE
|
||||
#else
|
||||
#define FRIEND_SEG_RX 0
|
||||
#define FRIEND_SUB_LIST_SIZE 0
|
||||
#endif
|
||||
|
||||
struct bt_mesh_friend {
|
||||
u16_t lpn;
|
||||
u8_t recv_delay;
|
||||
u8_t fsn:1,
|
||||
send_last:1,
|
||||
pending_req:1,
|
||||
sec_update:1,
|
||||
pending_buf:1,
|
||||
valid:1,
|
||||
established:1;
|
||||
s32_t poll_to;
|
||||
u16_t lpn_counter;
|
||||
u16_t counter;
|
||||
|
||||
u16_t net_idx;
|
||||
|
||||
u16_t sub_list[FRIEND_SUB_LIST_SIZE];
|
||||
|
||||
struct k_delayed_work timer;
|
||||
|
||||
struct bt_mesh_friend_seg {
|
||||
sys_slist_t queue;
|
||||
} seg[FRIEND_SEG_RX];
|
||||
|
||||
struct net_buf *last;
|
||||
|
||||
sys_slist_t queue;
|
||||
u32_t queue_size;
|
||||
|
||||
/* Friend Clear Procedure */
|
||||
struct {
|
||||
u32_t start; /* Clear Procedure start */
|
||||
u16_t frnd; /* Previous Friend's address */
|
||||
u16_t repeat_sec; /* Repeat timeout in seconds */
|
||||
struct k_delayed_work timer; /* Repeat timer */
|
||||
} clear;
|
||||
};
|
||||
|
||||
#if defined(CONFIG_BT_MESH_LOW_POWER)
|
||||
#define LPN_GROUPS CONFIG_BT_MESH_LOW_POWER
|
||||
#else
|
||||
#define LPN_GROUPS 0
|
||||
#endif
|
||||
|
||||
/* Low Power Node state */
|
||||
struct bt_mesh_lpn {
|
||||
enum __packed {
|
||||
BT_MESH_LPN_DISABLED, /* LPN feature is disabled */
|
||||
BT_MESH_LPN_CLEAR, /* Clear in progress */
|
||||
BT_MESH_LPN_TIMER, /* Waiting for auto timer expiry */
|
||||
BT_MESH_LPN_ENABLED, /* LPN enabled, but no Friend */
|
||||
BT_MESH_LPN_REQ_WAIT, /* Wait before scanning for offers */
|
||||
BT_MESH_LPN_WAIT_OFFER, /* Friend Req sent */
|
||||
BT_MESH_LPN_ESTABLISHED, /* Friendship established */
|
||||
BT_MESH_LPN_RECV_DELAY, /* Poll sent, waiting ReceiveDelay */
|
||||
BT_MESH_LPN_WAIT_UPDATE, /* Waiting for Update or message */
|
||||
} state;
|
||||
|
||||
/* Transaction Number (used for subscription list) */
|
||||
u8_t xact_next;
|
||||
u8_t xact_pending;
|
||||
u8_t sent_req;
|
||||
|
||||
/* Address of our Friend when we're a LPN. Unassigned if we don't
|
||||
* have a friend yet.
|
||||
*/
|
||||
u16_t frnd;
|
||||
|
||||
/* Value from the friend offer */
|
||||
u8_t recv_win;
|
||||
|
||||
u8_t req_attempts; /* Number of Request attempts */
|
||||
|
||||
s32_t poll_timeout;
|
||||
|
||||
u8_t groups_changed:1, /* Friend Subscription List needs updating */
|
||||
pending_poll:1, /* Poll to be sent after subscription */
|
||||
disable:1, /* Disable LPN after clearing */
|
||||
fsn:1, /* Friend Sequence Number */
|
||||
established:1, /* Friendship established */
|
||||
clear_success:1; /* Friend Clear Confirm received */
|
||||
|
||||
/* Friend Queue Size */
|
||||
u8_t queue_size;
|
||||
|
||||
/* LPNCounter */
|
||||
u16_t counter;
|
||||
|
||||
/* Previous Friend of this LPN */
|
||||
u16_t old_friend;
|
||||
|
||||
/* Duration reported for last advertising packet */
|
||||
u16_t adv_duration;
|
||||
|
||||
/* Next LPN related action timer */
|
||||
struct k_delayed_work timer;
|
||||
|
||||
/* Subscribed groups */
|
||||
u16_t groups[LPN_GROUPS];
|
||||
|
||||
/* Bit fields for tracking which groups the Friend knows about */
|
||||
ATOMIC_DEFINE(added, LPN_GROUPS);
|
||||
ATOMIC_DEFINE(pending, LPN_GROUPS);
|
||||
ATOMIC_DEFINE(to_remove, LPN_GROUPS);
|
||||
};
|
||||
|
||||
struct bt_mesh_net {
|
||||
u32_t iv_index; /* Current IV Index */
|
||||
u32_t seq:24, /* Next outgoing sequence number */
|
||||
iv_update:1, /* 1 if IV Update in Progress */
|
||||
ivu_initiator:1, /* IV Update initiated by us */
|
||||
ivu_test:1, /* IV Update test mode */
|
||||
pending_update:1, /* Update blocked by SDU in progress */
|
||||
valid:1; /* 0 if unused */
|
||||
|
||||
s64_t last_update; /* Time since last IV Update change */
|
||||
|
||||
/* Local network interface */
|
||||
struct k_work local_work;
|
||||
sys_slist_t local_queue;
|
||||
|
||||
#if defined(CONFIG_BT_MESH_FRIEND)
|
||||
/* Friend state, unique for each LPN that we're Friends for */
|
||||
struct bt_mesh_friend frnd[CONFIG_BT_MESH_FRIEND_LPN_COUNT];
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_BT_MESH_LOW_POWER)
|
||||
struct bt_mesh_lpn lpn; /* Low Power Node state */
|
||||
#endif
|
||||
|
||||
/* Timer to transition IV Update in Progress state */
|
||||
struct k_delayed_work ivu_complete;
|
||||
|
||||
u8_t dev_key[16];
|
||||
|
||||
struct bt_mesh_app_key app_keys[CONFIG_BT_MESH_APP_KEY_COUNT];
|
||||
|
||||
struct bt_mesh_subnet sub[CONFIG_BT_MESH_SUBNET_COUNT];
|
||||
|
||||
struct bt_mesh_rpl rpl[CONFIG_BT_MESH_CRPL];
|
||||
};
|
||||
|
||||
/* Network interface */
|
||||
enum bt_mesh_net_if {
|
||||
BT_MESH_NET_IF_ADV,
|
||||
BT_MESH_NET_IF_LOCAL,
|
||||
BT_MESH_NET_IF_PROXY,
|
||||
BT_MESH_NET_IF_PROXY_CFG,
|
||||
};
|
||||
|
||||
/* Decoding context for Network/Transport data */
|
||||
struct bt_mesh_net_rx {
|
||||
struct bt_mesh_subnet *sub;
|
||||
struct bt_mesh_msg_ctx ctx;
|
||||
u32_t seq; /* Sequence Number */
|
||||
u16_t dst; /* Destination address */
|
||||
u8_t old_iv:1, /* iv_index - 1 was used */
|
||||
new_key:1, /* Data was encrypted with updated key */
|
||||
friend_cred:1, /* Data was encrypted with friend cred */
|
||||
ctl:1, /* Network Control */
|
||||
net_if:2, /* Network interface */
|
||||
local_match:1, /* Matched a local element */
|
||||
friend_match:1; /* Matched an LPN we're friends for */
|
||||
s8_t rssi;
|
||||
};
|
||||
|
||||
/* Encoding context for Network/Transport data */
|
||||
struct bt_mesh_net_tx {
|
||||
struct bt_mesh_subnet *sub;
|
||||
struct bt_mesh_msg_ctx *ctx;
|
||||
u16_t src;
|
||||
u8_t xmit;
|
||||
u8_t friend_cred:1,
|
||||
aszmic:1,
|
||||
aid:6;
|
||||
};
|
||||
|
||||
extern struct bt_mesh_net bt_mesh;
|
||||
|
||||
#define BT_MESH_NET_IVI_TX (bt_mesh.iv_index - bt_mesh.iv_update)
|
||||
#define BT_MESH_NET_IVI_RX(rx) (bt_mesh.iv_index - (rx)->old_iv)
|
||||
|
||||
#define BT_MESH_NET_HDR_LEN 9
|
||||
|
||||
int bt_mesh_net_keys_create(struct bt_mesh_subnet_keys *keys,
|
||||
const u8_t key[16]);
|
||||
|
||||
int bt_mesh_net_create(u16_t idx, u8_t flags, const u8_t key[16],
|
||||
u32_t iv_index);
|
||||
|
||||
u8_t bt_mesh_net_flags(struct bt_mesh_subnet *sub);
|
||||
|
||||
bool bt_mesh_kr_update(struct bt_mesh_subnet *sub, u8_t new_kr, bool new_key);
|
||||
|
||||
void bt_mesh_net_revoke_keys(struct bt_mesh_subnet *sub);
|
||||
|
||||
int bt_mesh_net_beacon_update(struct bt_mesh_subnet *sub);
|
||||
|
||||
void bt_mesh_rpl_reset(void);
|
||||
|
||||
bool bt_mesh_net_iv_update(u32_t iv_index, bool iv_update);
|
||||
|
||||
void bt_mesh_net_sec_update(struct bt_mesh_subnet *sub);
|
||||
|
||||
struct bt_mesh_subnet *bt_mesh_subnet_get(u16_t net_idx);
|
||||
|
||||
struct bt_mesh_subnet *bt_mesh_subnet_find(const u8_t net_id[8], u8_t flags,
|
||||
u32_t iv_index, const u8_t auth[8],
|
||||
bool *new_key);
|
||||
|
||||
int bt_mesh_net_encode(struct bt_mesh_net_tx *tx, struct net_buf_simple *buf,
|
||||
bool proxy);
|
||||
|
||||
int bt_mesh_net_send(struct bt_mesh_net_tx *tx, struct net_buf *buf,
|
||||
const struct bt_mesh_send_cb *cb, void *cb_data);
|
||||
|
||||
int bt_mesh_net_resend(struct bt_mesh_subnet *sub, struct net_buf *buf,
|
||||
bool new_key, const struct bt_mesh_send_cb *cb,
|
||||
void *cb_data);
|
||||
|
||||
int bt_mesh_net_decode(struct net_buf_simple *data, enum bt_mesh_net_if net_if,
|
||||
struct bt_mesh_net_rx *rx, struct net_buf_simple *buf);
|
||||
|
||||
void bt_mesh_net_recv(struct net_buf_simple *data, s8_t rssi,
|
||||
enum bt_mesh_net_if net_if);
|
||||
|
||||
void bt_mesh_net_init(void);
|
||||
|
||||
/* Friendship Credential Management */
|
||||
struct friend_cred {
|
||||
u16_t net_idx;
|
||||
u16_t addr;
|
||||
|
||||
u16_t lpn_counter;
|
||||
u16_t frnd_counter;
|
||||
|
||||
struct {
|
||||
u8_t nid; /* NID */
|
||||
u8_t enc[16]; /* EncKey */
|
||||
u8_t privacy[16]; /* PrivacyKey */
|
||||
} cred[2];
|
||||
};
|
||||
|
||||
int friend_cred_get(struct bt_mesh_subnet *sub, u16_t addr, u8_t *nid,
|
||||
const u8_t **enc, const u8_t **priv);
|
||||
int friend_cred_set(struct friend_cred *cred, u8_t idx, const u8_t net_key[16]);
|
||||
void friend_cred_refresh(u16_t net_idx);
|
||||
int friend_cred_update(struct bt_mesh_subnet *sub);
|
||||
struct friend_cred *friend_cred_create(struct bt_mesh_subnet *sub, u16_t addr,
|
||||
u16_t lpn_counter, u16_t frnd_counter);
|
||||
void friend_cred_clear(struct friend_cred *cred);
|
||||
int friend_cred_del(u16_t net_idx, u16_t addr);
|
||||
1580
Living_SDK/kernel/protocols/bluetooth/host/bt_mesh/prov.c
Normal file
1580
Living_SDK/kernel/protocols/bluetooth/host/bt_mesh/prov.c
Normal file
File diff suppressed because it is too large
Load diff
22
Living_SDK/kernel/protocols/bluetooth/host/bt_mesh/prov.h
Normal file
22
Living_SDK/kernel/protocols/bluetooth/host/bt_mesh/prov.h
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
/* Bluetooth Mesh */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2017 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
void bt_mesh_pb_adv_recv(struct net_buf_simple *buf);
|
||||
|
||||
bool bt_prov_active(void);
|
||||
|
||||
int bt_mesh_pb_gatt_open(struct bt_conn *conn);
|
||||
int bt_mesh_pb_gatt_close(struct bt_conn *conn);
|
||||
int bt_mesh_pb_gatt_recv(struct bt_conn *conn, struct net_buf_simple *buf);
|
||||
|
||||
const u8_t *bt_mesh_prov_get_uuid(void);
|
||||
|
||||
int bt_mesh_prov_init(const struct bt_mesh_prov *prov);
|
||||
|
||||
void bt_mesh_prov_complete(u16_t net_idx, u16_t addr);
|
||||
void bt_mesh_prov_reset(void);
|
||||
1225
Living_SDK/kernel/protocols/bluetooth/host/bt_mesh/proxy.c
Normal file
1225
Living_SDK/kernel/protocols/bluetooth/host/bt_mesh/proxy.c
Normal file
File diff suppressed because it is too large
Load diff
37
Living_SDK/kernel/protocols/bluetooth/host/bt_mesh/proxy.h
Normal file
37
Living_SDK/kernel/protocols/bluetooth/host/bt_mesh/proxy.h
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
/* Bluetooth Mesh */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2017 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#define BT_MESH_PROXY_NET_PDU 0x00
|
||||
#define BT_MESH_PROXY_BEACON 0x01
|
||||
#define BT_MESH_PROXY_CONFIG 0x02
|
||||
#define BT_MESH_PROXY_PROV 0x03
|
||||
|
||||
int bt_mesh_proxy_send(struct bt_conn *conn, u8_t type,
|
||||
struct net_buf_simple *msg);
|
||||
|
||||
int bt_mesh_proxy_prov_enable(void);
|
||||
int bt_mesh_proxy_prov_disable(void);
|
||||
|
||||
int bt_mesh_proxy_gatt_enable(void);
|
||||
int bt_mesh_proxy_gatt_disable(void);
|
||||
void bt_mesh_proxy_gatt_disconnect(void);
|
||||
|
||||
void bt_mesh_proxy_beacon_send(struct bt_mesh_subnet *sub);
|
||||
|
||||
struct net_buf_simple *bt_mesh_proxy_get_buf(void);
|
||||
|
||||
s32_t bt_mesh_proxy_adv_start(void);
|
||||
void bt_mesh_proxy_adv_stop(void);
|
||||
|
||||
void bt_mesh_proxy_identity_start(struct bt_mesh_subnet *sub);
|
||||
void bt_mesh_proxy_identity_stop(struct bt_mesh_subnet *sub);
|
||||
|
||||
bool bt_mesh_proxy_relay(struct net_buf_simple *buf, u16_t dst);
|
||||
void bt_mesh_proxy_addr_add(struct net_buf_simple *buf, u16_t addr);
|
||||
|
||||
int bt_mesh_proxy_init(void);
|
||||
1949
Living_SDK/kernel/protocols/bluetooth/host/bt_mesh/shell.c
Normal file
1949
Living_SDK/kernel/protocols/bluetooth/host/bt_mesh/shell.c
Normal file
File diff suppressed because it is too large
Load diff
22
Living_SDK/kernel/protocols/bluetooth/host/bt_mesh/test.c
Normal file
22
Living_SDK/kernel/protocols/bluetooth/host/bt_mesh/test.c
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
/* Bluetooth Mesh */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2017 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <bluetooth/mesh.h>
|
||||
|
||||
#include "common/log.h"
|
||||
|
||||
#include "mesh.h"
|
||||
#include "test.h"
|
||||
|
||||
int bt_mesh_test(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
16
Living_SDK/kernel/protocols/bluetooth/host/bt_mesh/test.h
Normal file
16
Living_SDK/kernel/protocols/bluetooth/host/bt_mesh/test.h
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
/* Bluetooth Mesh */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2017 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#if defined(CONFIG_BT_MESH_SELF_TEST)
|
||||
int bt_mesh_test(void);
|
||||
#else
|
||||
static inline int bt_mesh_test(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
1383
Living_SDK/kernel/protocols/bluetooth/host/bt_mesh/transport.c
Normal file
1383
Living_SDK/kernel/protocols/bluetooth/host/bt_mesh/transport.c
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,97 @@
|
|||
/* Bluetooth Mesh */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2017 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#define TRANS_SEQ_AUTH_NVAL 0xffffffffffffffff
|
||||
|
||||
#define BT_MESH_TX_SEG_COUNT (CONFIG_BT_MESH_ADV_BUF_COUNT - 3)
|
||||
#define BT_MESH_TX_SDU_MAX (BT_MESH_TX_SEG_COUNT * 12)
|
||||
|
||||
#define TRANS_CTL_OP_MASK ((u8_t)BIT_MASK(7))
|
||||
#define TRANS_CTL_OP(data) ((data)[0] & TRANS_CTL_OP_MASK)
|
||||
#define TRANS_CTL_HDR(op, seg) ((op & TRANS_CTL_OP_MASK) | (seg << 7))
|
||||
|
||||
#define TRANS_CTL_OP_ACK 0x00
|
||||
#define TRANS_CTL_OP_FRIEND_POLL 0x01
|
||||
#define TRANS_CTL_OP_FRIEND_UPDATE 0x02
|
||||
#define TRANS_CTL_OP_FRIEND_REQ 0x03
|
||||
#define TRANS_CTL_OP_FRIEND_OFFER 0x04
|
||||
#define TRANS_CTL_OP_FRIEND_CLEAR 0x05
|
||||
#define TRANS_CTL_OP_FRIEND_CLEAR_CFM 0x06
|
||||
#define TRANS_CTL_OP_FRIEND_SUB_ADD 0x07
|
||||
#define TRANS_CTL_OP_FRIEND_SUB_REM 0x08
|
||||
#define TRANS_CTL_OP_FRIEND_SUB_CFM 0x09
|
||||
#define TRANS_CTL_OP_HEARTBEAT 0x0a
|
||||
|
||||
struct bt_mesh_ctl_friend_poll {
|
||||
u8_t fsn;
|
||||
} __packed;
|
||||
|
||||
struct bt_mesh_ctl_friend_update {
|
||||
u8_t flags;
|
||||
u32_t iv_index;
|
||||
u8_t md;
|
||||
} __packed;
|
||||
|
||||
struct bt_mesh_ctl_friend_req {
|
||||
u8_t criteria;
|
||||
u8_t recv_delay;
|
||||
u8_t poll_to[3];
|
||||
u16_t prev_addr;
|
||||
u8_t num_elem;
|
||||
u16_t lpn_counter;
|
||||
} __packed;
|
||||
|
||||
struct bt_mesh_ctl_friend_offer {
|
||||
u8_t recv_win;
|
||||
u8_t queue_size;
|
||||
u8_t sub_list_size;
|
||||
s8_t rssi;
|
||||
u16_t frnd_counter;
|
||||
} __packed;
|
||||
|
||||
struct bt_mesh_ctl_friend_clear {
|
||||
u16_t lpn_addr;
|
||||
u16_t lpn_counter;
|
||||
} __packed;
|
||||
|
||||
struct bt_mesh_ctl_friend_clear_confirm {
|
||||
u16_t lpn_addr;
|
||||
u16_t lpn_counter;
|
||||
} __packed;
|
||||
|
||||
#define BT_MESH_FRIEND_SUB_MIN_LEN (1 + 2)
|
||||
struct bt_mesh_ctl_friend_sub {
|
||||
u8_t xact;
|
||||
u16_t addr_list[5];
|
||||
} __packed;
|
||||
|
||||
struct bt_mesh_ctl_friend_sub_confirm {
|
||||
u8_t xact;
|
||||
} __packed;
|
||||
|
||||
void bt_mesh_set_hb_sub_dst(u16_t addr);
|
||||
|
||||
struct bt_mesh_app_key *bt_mesh_app_key_find(u16_t app_idx);
|
||||
|
||||
bool bt_mesh_tx_in_progress(void);
|
||||
|
||||
void bt_mesh_rx_reset(void);
|
||||
void bt_mesh_tx_reset(void);
|
||||
|
||||
int bt_mesh_ctl_send(struct bt_mesh_net_tx *tx, u8_t ctl_op, void *data,
|
||||
size_t data_len, u64_t *seq_auth,
|
||||
const struct bt_mesh_send_cb *cb, void *cb_data);
|
||||
|
||||
int bt_mesh_trans_send(struct bt_mesh_net_tx *tx, struct net_buf_simple *msg,
|
||||
const struct bt_mesh_send_cb *cb, void *cb_data);
|
||||
|
||||
int bt_mesh_trans_recv(struct net_buf_simple *buf, struct bt_mesh_net_rx *rx);
|
||||
|
||||
void bt_mesh_trans_init(void);
|
||||
|
||||
void bt_mesh_rpl_clear(void);
|
||||
2123
Living_SDK/kernel/protocols/bluetooth/host/conn.c
Normal file
2123
Living_SDK/kernel/protocols/bluetooth/host/conn.c
Normal file
File diff suppressed because it is too large
Load diff
221
Living_SDK/kernel/protocols/bluetooth/host/conn_internal.h
Normal file
221
Living_SDK/kernel/protocols/bluetooth/host/conn_internal.h
Normal file
|
|
@ -0,0 +1,221 @@
|
|||
/** @file
|
||||
* @brief Internal APIs for Bluetooth connection handling.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2015 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
typedef enum __packed {
|
||||
BT_CONN_DISCONNECTED,
|
||||
BT_CONN_CONNECT_SCAN,
|
||||
BT_CONN_CONNECT,
|
||||
BT_CONN_CONNECTED,
|
||||
BT_CONN_DISCONNECT,
|
||||
} bt_conn_state_t;
|
||||
|
||||
/* bt_conn flags: the flags defined here represent connection parameters */
|
||||
enum {
|
||||
BT_CONN_AUTO_CONNECT,
|
||||
BT_CONN_BR_LEGACY_SECURE, /* 16 digits legacy PIN tracker */
|
||||
BT_CONN_USER, /* user I/O when pairing */
|
||||
BT_CONN_BR_PAIRING, /* BR connection in pairing context */
|
||||
BT_CONN_BR_NOBOND, /* SSP no bond pairing tracker */
|
||||
BT_CONN_BR_PAIRING_INITIATOR, /* local host starts authentication */
|
||||
BT_CONN_CLEANUP, /* Disconnected, pending cleanup */
|
||||
BT_CONN_AUTO_PHY_UPDATE, /* Auto-update PHY */
|
||||
BT_CONN_AUTO_DATA_LEN, /* Auto data len change in progress */
|
||||
|
||||
/* Total number of flags - must be at the end of the enum */
|
||||
BT_CONN_NUM_FLAGS,
|
||||
};
|
||||
|
||||
struct bt_conn_le {
|
||||
bt_addr_le_t dst;
|
||||
|
||||
bt_addr_le_t init_addr;
|
||||
bt_addr_le_t resp_addr;
|
||||
|
||||
u16_t interval;
|
||||
u16_t interval_min;
|
||||
u16_t interval_max;
|
||||
|
||||
u16_t latency;
|
||||
u16_t timeout;
|
||||
|
||||
u8_t features[8];
|
||||
|
||||
struct bt_keys *keys;
|
||||
|
||||
/* Delayed work for connection update and timeout handling */
|
||||
struct k_delayed_work update_work;
|
||||
};
|
||||
|
||||
#if defined(CONFIG_BT_BREDR)
|
||||
/* For now reserve space for 2 pages of LMP remote features */
|
||||
#define LMP_MAX_PAGES 2
|
||||
|
||||
struct bt_conn_br {
|
||||
bt_addr_t dst;
|
||||
u8_t remote_io_capa;
|
||||
u8_t remote_auth;
|
||||
u8_t pairing_method;
|
||||
/* remote LMP features pages per 8 bytes each */
|
||||
u8_t features[LMP_MAX_PAGES][8];
|
||||
|
||||
struct bt_keys_link_key *link_key;
|
||||
};
|
||||
|
||||
struct bt_conn_sco {
|
||||
/* Reference to ACL Connection */
|
||||
struct bt_conn *acl;
|
||||
u16_t pkt_type;
|
||||
};
|
||||
#endif
|
||||
|
||||
typedef void (*bt_conn_tx_cb_t)(struct bt_conn *conn);
|
||||
|
||||
struct bt_conn_tx {
|
||||
sys_snode_t node;
|
||||
bt_conn_tx_cb_t cb;
|
||||
};
|
||||
|
||||
struct bt_conn {
|
||||
u16_t handle;
|
||||
u8_t type;
|
||||
u8_t role;
|
||||
|
||||
ATOMIC_DEFINE(flags, BT_CONN_NUM_FLAGS);
|
||||
|
||||
#if defined(CONFIG_BT_SMP) || defined(CONFIG_BT_BREDR)
|
||||
bt_security_t sec_level;
|
||||
bt_security_t required_sec_level;
|
||||
u8_t encrypt;
|
||||
#endif /* CONFIG_BT_SMP || CONFIG_BT_BREDR */
|
||||
|
||||
/* Connection error or reason for disconnect */
|
||||
u8_t err;
|
||||
|
||||
bt_conn_state_t state;
|
||||
|
||||
u16_t rx_len;
|
||||
struct net_buf *rx;
|
||||
|
||||
/* Sent but not acknowledged TX packets */
|
||||
sys_slist_t tx_pending;
|
||||
/* Acknowledged but not yet notified TX packets */
|
||||
struct k_fifo tx_notify;
|
||||
|
||||
/* Queue for outgoing ACL data */
|
||||
struct k_fifo tx_queue;
|
||||
|
||||
/* Active L2CAP channels */
|
||||
sys_slist_t channels;
|
||||
|
||||
atomic_t ref;
|
||||
|
||||
union {
|
||||
struct bt_conn_le le;
|
||||
#if defined(CONFIG_BT_BREDR)
|
||||
struct bt_conn_br br;
|
||||
struct bt_conn_sco sco;
|
||||
#endif
|
||||
};
|
||||
};
|
||||
|
||||
/* Process incoming data for a connection */
|
||||
void bt_conn_recv(struct bt_conn *conn, struct net_buf *buf, u8_t flags);
|
||||
|
||||
/* Send data over a connection */
|
||||
int bt_conn_send_cb(struct bt_conn *conn, struct net_buf *buf,
|
||||
bt_conn_tx_cb_t cb);
|
||||
|
||||
static inline int bt_conn_send(struct bt_conn *conn, struct net_buf *buf)
|
||||
{
|
||||
return bt_conn_send_cb(conn, buf, NULL);
|
||||
}
|
||||
|
||||
/* Add a new LE connection */
|
||||
struct bt_conn *bt_conn_add_le(const bt_addr_le_t *peer);
|
||||
|
||||
/* Add a new BR/EDR connection */
|
||||
struct bt_conn *bt_conn_add_br(const bt_addr_t *peer);
|
||||
|
||||
/* Add a new SCO connection */
|
||||
struct bt_conn *bt_conn_add_sco(const bt_addr_t *peer, int link_type);
|
||||
|
||||
/* Cleanup SCO references */
|
||||
void bt_sco_cleanup(struct bt_conn *sco_conn);
|
||||
|
||||
/* Look up an existing sco connection by BT address */
|
||||
struct bt_conn *bt_conn_lookup_addr_sco(const bt_addr_t *peer);
|
||||
|
||||
/* Look up an existing connection by BT address */
|
||||
struct bt_conn *bt_conn_lookup_addr_br(const bt_addr_t *peer);
|
||||
|
||||
void bt_conn_pin_code_req(struct bt_conn *conn);
|
||||
u8_t bt_conn_get_io_capa(void);
|
||||
u8_t bt_conn_ssp_get_auth(const struct bt_conn *conn);
|
||||
void bt_conn_ssp_auth(struct bt_conn *conn, u32_t passkey);
|
||||
|
||||
void bt_conn_disconnect_all(void);
|
||||
|
||||
/* Look up an existing connection */
|
||||
struct bt_conn *bt_conn_lookup_handle(u16_t handle);
|
||||
|
||||
/* Compare an address with bt_conn destination address */
|
||||
int bt_conn_addr_le_cmp(const struct bt_conn *conn, const bt_addr_le_t *peer);
|
||||
|
||||
|
||||
/* Helpers for identifying & looking up connections based on the the index to
|
||||
* the connection list. This is useful for O(1) lookups, but can't be used
|
||||
* e.g. as the handle since that's assigned to us by the controller.
|
||||
*/
|
||||
#define BT_CONN_ID_INVALID 0xff
|
||||
u8_t bt_conn_get_id(struct bt_conn *conn);
|
||||
struct bt_conn *bt_conn_lookup_id(u8_t id);
|
||||
|
||||
/* Look up a connection state. For BT_ADDR_LE_ANY, returns the first connection
|
||||
* with the specific state
|
||||
*/
|
||||
struct bt_conn *bt_conn_lookup_state_le(const bt_addr_le_t *peer,
|
||||
const bt_conn_state_t state);
|
||||
|
||||
/* Set connection object in certain state and perform action related to state */
|
||||
void bt_conn_set_state(struct bt_conn *conn, bt_conn_state_t state);
|
||||
|
||||
int bt_conn_le_conn_update(struct bt_conn *conn,
|
||||
const struct bt_le_conn_param *param);
|
||||
|
||||
void notify_le_param_updated(struct bt_conn *conn);
|
||||
|
||||
bool le_param_req(struct bt_conn *conn, struct bt_le_conn_param *param);
|
||||
|
||||
#if defined(CONFIG_BT_SMP)
|
||||
/* rand and ediv should be in BT order */
|
||||
int bt_conn_le_start_encryption(struct bt_conn *conn, u64_t rand,
|
||||
u16_t ediv, const u8_t *ltk, size_t len);
|
||||
|
||||
/* Notify higher layers that RPA was resolved */
|
||||
void bt_conn_identity_resolved(struct bt_conn *conn);
|
||||
#endif /* CONFIG_BT_SMP */
|
||||
|
||||
#if defined(CONFIG_BT_SMP) || defined(CONFIG_BT_BREDR)
|
||||
/* Notify higher layers that connection security changed */
|
||||
void bt_conn_security_changed(struct bt_conn *conn);
|
||||
#endif /* CONFIG_BT_SMP || CONFIG_BT_BREDR */
|
||||
|
||||
/* Prepare a PDU to be sent over a connection */
|
||||
struct net_buf *bt_conn_create_pdu(struct net_buf_pool *pool, size_t reserve);
|
||||
|
||||
/* Initialize connection management */
|
||||
int bt_conn_init(void);
|
||||
|
||||
/* Selects based on connecton type right semaphore for ACL packets */
|
||||
struct k_sem *bt_conn_get_pkts(struct bt_conn *conn);
|
||||
|
||||
/* k_poll related helpers for the TX thread */
|
||||
int bt_conn_prepare_events(struct k_poll_event events[]);
|
||||
void bt_conn_process_tx(struct bt_conn *conn);
|
||||
void bt_conn_notify_tx(struct bt_conn *conn);
|
||||
160
Living_SDK/kernel/protocols/bluetooth/host/crypto.c
Normal file
160
Living_SDK/kernel/protocols/bluetooth/host/crypto.c
Normal file
|
|
@ -0,0 +1,160 @@
|
|||
/*
|
||||
* Copyright (c) 2017 Nordic Semiconductor ASA
|
||||
* Copyright (c) 2015-2016 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <zephyr.h>
|
||||
#include <misc/byteorder.h>
|
||||
|
||||
#include <bluetooth/bluetooth.h>
|
||||
#include <bluetooth/hci.h>
|
||||
#include <bluetooth/conn.h>
|
||||
|
||||
#include <tinycrypt/constants.h>
|
||||
#include <tinycrypt/hmac_prng.h>
|
||||
#include <tinycrypt/aes.h>
|
||||
#include <tinycrypt/utils.h>
|
||||
|
||||
#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_DEBUG_HCI_CORE)
|
||||
#include "common/log.h"
|
||||
|
||||
#include "hci_core.h"
|
||||
|
||||
static struct tc_hmac_prng_struct prng;
|
||||
|
||||
static int prng_reseed(struct tc_hmac_prng_struct *h)
|
||||
{
|
||||
u8_t seed[32];
|
||||
s64_t extra;
|
||||
int ret, i;
|
||||
|
||||
for (i = 0; i < (sizeof(seed) / 8); i++) {
|
||||
struct bt_hci_rp_le_rand *rp;
|
||||
struct net_buf *rsp;
|
||||
|
||||
ret = bt_hci_cmd_send_sync(BT_HCI_OP_LE_RAND, NULL, &rsp);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
rp = (void *)rsp->data;
|
||||
memcpy(&seed[i * 8], rp->rand, 8);
|
||||
|
||||
net_buf_unref(rsp);
|
||||
}
|
||||
|
||||
extra = k_uptime_get();
|
||||
|
||||
ret = tc_hmac_prng_reseed(h, seed, sizeof(seed), (u8_t *)&extra,
|
||||
sizeof(extra));
|
||||
if (ret == TC_CRYPTO_FAIL) {
|
||||
BT_ERR("Failed to re-seed PRNG");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int prng_init(void)
|
||||
{
|
||||
struct bt_hci_rp_le_rand *rp;
|
||||
struct net_buf *rsp;
|
||||
int ret;
|
||||
|
||||
/* Check first that HCI_LE_Rand is supported */
|
||||
if (!(bt_dev.supported_commands[27] & BIT(7))) {
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
ret = bt_hci_cmd_send_sync(BT_HCI_OP_LE_RAND, NULL, &rsp);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
rp = (void *)rsp->data;
|
||||
|
||||
ret = tc_hmac_prng_init(&prng, rp->rand, sizeof(rp->rand));
|
||||
|
||||
net_buf_unref(rsp);
|
||||
|
||||
if (ret == TC_CRYPTO_FAIL) {
|
||||
BT_ERR("Failed to initialize PRNG");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* re-seed is needed after init */
|
||||
return prng_reseed(&prng);
|
||||
}
|
||||
|
||||
int bt_rand(void *buf, size_t len)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = tc_hmac_prng_generate(buf, len, &prng);
|
||||
if (ret == TC_HMAC_PRNG_RESEED_REQ) {
|
||||
ret = prng_reseed(&prng);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = tc_hmac_prng_generate(buf, len, &prng);
|
||||
}
|
||||
|
||||
if (ret == TC_CRYPTO_SUCCESS) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
int bt_encrypt_le(const u8_t key[16], const u8_t plaintext[16],
|
||||
u8_t enc_data[16])
|
||||
{
|
||||
struct tc_aes_key_sched_struct s;
|
||||
u8_t tmp[16];
|
||||
|
||||
BT_DBG("key %s plaintext %s", bt_hex(key, 16), bt_hex(plaintext, 16));
|
||||
|
||||
sys_memcpy_swap(tmp, key, 16);
|
||||
|
||||
if (tc_aes128_set_encrypt_key(&s, tmp) == TC_CRYPTO_FAIL) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
sys_memcpy_swap(tmp, plaintext, 16);
|
||||
|
||||
if (tc_aes_encrypt(enc_data, tmp, &s) == TC_CRYPTO_FAIL) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
sys_mem_swap(enc_data, 16);
|
||||
|
||||
BT_DBG("enc_data %s", bt_hex(enc_data, 16));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bt_encrypt_be(const u8_t key[16], const u8_t plaintext[16],
|
||||
u8_t enc_data[16])
|
||||
{
|
||||
struct tc_aes_key_sched_struct s;
|
||||
|
||||
BT_DBG("key %s plaintext %s", bt_hex(key, 16), bt_hex(plaintext, 16));
|
||||
|
||||
if (tc_aes128_set_encrypt_key(&s, key) == TC_CRYPTO_FAIL) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (tc_aes_encrypt(enc_data, plaintext, &s) == TC_CRYPTO_FAIL) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
BT_DBG("enc_data %s", bt_hex(enc_data, 16));
|
||||
|
||||
return 0;
|
||||
}
|
||||
8
Living_SDK/kernel/protocols/bluetooth/host/crypto.h
Normal file
8
Living_SDK/kernel/protocols/bluetooth/host/crypto.h
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
/*
|
||||
* Copyright (c) 2016-2017 Nordic Semiconductor ASA
|
||||
* Copyright (c) 2015-2016 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
int prng_init(void);
|
||||
63
Living_SDK/kernel/protocols/bluetooth/host/ecc.h
Normal file
63
Living_SDK/kernel/protocols/bluetooth/host/ecc.h
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
/* ecc.h - ECDH helpers */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2016 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/* @brief Container for public key callback */
|
||||
struct bt_pub_key_cb {
|
||||
/** @brief Callback type for Public Key generation.
|
||||
*
|
||||
* Used to notify of the local public key or that the local key is not
|
||||
* available (either because of a failure to read it or because it is
|
||||
* being regenerated).
|
||||
*
|
||||
* @param key The local public key, or NULL in case of no key.
|
||||
*/
|
||||
void (*func)(const u8_t key[64]);
|
||||
|
||||
struct bt_pub_key_cb *_next;
|
||||
};
|
||||
|
||||
/* @brief Generate a new Public Key.
|
||||
*
|
||||
* Generate a new ECC Public Key. The callback will persist even after the
|
||||
* key has been generated, and will be used to notify of new generation
|
||||
* processes (NULL as key).
|
||||
*
|
||||
* @param cb Callback to notify the new key, or NULL to request an update
|
||||
* without registering any new callback.
|
||||
*
|
||||
* @return Zero on success or negative error code otherwise
|
||||
*/
|
||||
int bt_pub_key_gen(struct bt_pub_key_cb *cb);
|
||||
|
||||
/* @brief Get the current Public Key.
|
||||
*
|
||||
* Get the current ECC Public Key.
|
||||
*
|
||||
* @return Current key, or NULL if not available.
|
||||
*/
|
||||
const u8_t *bt_pub_key_get(void);
|
||||
|
||||
/* @typedef bt_dh_key_cb_t
|
||||
* @brief Callback type for DH Key calculation.
|
||||
*
|
||||
* Used to notify of the calculated DH Key.
|
||||
*
|
||||
* @param key The DH Key, or NULL in case of failure.
|
||||
*/
|
||||
typedef void (*bt_dh_key_cb_t)(const u8_t key[32]);
|
||||
|
||||
/* @brief Calculate a DH Key from a remote Public Key.
|
||||
*
|
||||
* Calculate a DH Key from the remote Public Key.
|
||||
*
|
||||
* @param remote_pk Remote Public Key.
|
||||
* @param cb Callback to notify the calculated key.
|
||||
*
|
||||
* @return Zero on success or negative error code otherwise
|
||||
*/
|
||||
int bt_dh_key_gen(const u8_t remote_pk[64], bt_dh_key_cb_t cb);
|
||||
2087
Living_SDK/kernel/protocols/bluetooth/host/gatt.c
Normal file
2087
Living_SDK/kernel/protocols/bluetooth/host/gatt.c
Normal file
File diff suppressed because it is too large
Load diff
23
Living_SDK/kernel/protocols/bluetooth/host/gatt_internal.h
Normal file
23
Living_SDK/kernel/protocols/bluetooth/host/gatt_internal.h
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
/** @file
|
||||
* @brief Internal API for Generic Attribute Profile handling.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2015-2016 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
void bt_gatt_init(void);
|
||||
void bt_gatt_connected(struct bt_conn *conn);
|
||||
void bt_gatt_disconnected(struct bt_conn *conn);
|
||||
|
||||
#if defined(CONFIG_BT_GATT_CLIENT)
|
||||
void bt_gatt_notification(struct bt_conn *conn, u16_t handle,
|
||||
const void *data, u16_t length);
|
||||
#else
|
||||
static inline void bt_gatt_notification(struct bt_conn *conn, u16_t handle,
|
||||
const void *data, u16_t length)
|
||||
{
|
||||
}
|
||||
#endif /* CONFIG_BT_GATT_CLIENT */
|
||||
5299
Living_SDK/kernel/protocols/bluetooth/host/hci_core.c
Normal file
5299
Living_SDK/kernel/protocols/bluetooth/host/hci_core.c
Normal file
File diff suppressed because it is too large
Load diff
192
Living_SDK/kernel/protocols/bluetooth/host/hci_core.h
Normal file
192
Living_SDK/kernel/protocols/bluetooth/host/hci_core.h
Normal file
|
|
@ -0,0 +1,192 @@
|
|||
/* hci_core.h - Bluetooth HCI core access */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2015-2016 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/* LL connection parameters */
|
||||
#define LE_CONN_LATENCY 0x0000
|
||||
#define LE_CONN_TIMEOUT 0x002a
|
||||
|
||||
#if defined(CONFIG_BT_BREDR)
|
||||
#define LMP_FEAT_PAGES_COUNT 3
|
||||
#else
|
||||
#define LMP_FEAT_PAGES_COUNT 1
|
||||
#endif
|
||||
|
||||
/* SCO settings */
|
||||
#define BT_VOICE_CVSD_16BIT 0x0060
|
||||
|
||||
/* k_poll event tags */
|
||||
enum {
|
||||
BT_EVENT_CMD_TX,
|
||||
BT_EVENT_CONN_TX_NOTIFY,
|
||||
BT_EVENT_CONN_TX_QUEUE,
|
||||
};
|
||||
|
||||
/* bt_dev flags: the flags defined here represent BT controller state */
|
||||
enum {
|
||||
BT_DEV_ENABLE,
|
||||
BT_DEV_READY,
|
||||
BT_DEV_ID_STATIC_RANDOM,
|
||||
BT_DEV_HAS_PUB_KEY,
|
||||
BT_DEV_PUB_KEY_BUSY,
|
||||
|
||||
BT_DEV_ADVERTISING,
|
||||
BT_DEV_KEEP_ADVERTISING,
|
||||
BT_DEV_SCANNING,
|
||||
BT_DEV_EXPLICIT_SCAN,
|
||||
BT_DEV_ACTIVE_SCAN,
|
||||
BT_DEV_SCAN_FILTER_DUP,
|
||||
|
||||
BT_DEV_RPA_VALID,
|
||||
|
||||
BT_DEV_ID_PENDING,
|
||||
|
||||
#if defined(CONFIG_BT_BREDR)
|
||||
BT_DEV_ISCAN,
|
||||
BT_DEV_PSCAN,
|
||||
BT_DEV_INQUIRY,
|
||||
#endif /* CONFIG_BT_BREDR */
|
||||
|
||||
/* Total number of flags - must be at the end of the enum */
|
||||
BT_DEV_NUM_FLAGS,
|
||||
};
|
||||
|
||||
struct bt_dev_le {
|
||||
/* LE features */
|
||||
u8_t features[8];
|
||||
/* LE states */
|
||||
u64_t states;
|
||||
|
||||
#if defined(CONFIG_BT_CONN)
|
||||
/* Controller buffer information */
|
||||
u16_t mtu;
|
||||
struct k_sem pkts;
|
||||
#endif /* CONFIG_BT_CONN */
|
||||
|
||||
#if defined(CONFIG_BT_SMP)
|
||||
/* Size of the the controller resolving list */
|
||||
u8_t rl_size;
|
||||
/* Number of entries in the resolving list. rl_entries > rl_size
|
||||
* means that host-side resolving is used.
|
||||
*/
|
||||
u8_t rl_entries;
|
||||
#endif /* CONFIG_BT_SMP */
|
||||
};
|
||||
|
||||
#if defined(CONFIG_BT_BREDR)
|
||||
struct bt_dev_br {
|
||||
/* Max controller's acceptable ACL packet length */
|
||||
u16_t mtu;
|
||||
struct k_sem pkts;
|
||||
u16_t esco_pkt_type;
|
||||
};
|
||||
#endif
|
||||
|
||||
/* The theoretical max for these is 8 and 64, but there's no point
|
||||
* in allocating the full memory if we only support a small subset.
|
||||
* These values must be updated whenever the host implementation is
|
||||
* extended beyond the current values.
|
||||
*/
|
||||
#define BT_DEV_VS_FEAT_MAX 1
|
||||
#define BT_DEV_VS_CMDS_MAX 2
|
||||
|
||||
/* State tracking for the local Bluetooth controller */
|
||||
struct bt_dev {
|
||||
/* Local Identity Address */
|
||||
bt_addr_le_t id_addr;
|
||||
|
||||
/* Current local Random Address */
|
||||
bt_addr_le_t random_addr;
|
||||
|
||||
/* Controller version & manufacturer information */
|
||||
u8_t hci_version;
|
||||
u8_t lmp_version;
|
||||
u16_t hci_revision;
|
||||
u16_t lmp_subversion;
|
||||
u16_t manufacturer;
|
||||
|
||||
/* LMP features (pages 0, 1, 2) */
|
||||
u8_t features[LMP_FEAT_PAGES_COUNT][8];
|
||||
|
||||
/* Supported commands */
|
||||
u8_t supported_commands[64];
|
||||
|
||||
#if defined(CONFIG_BT_HCI_VS_EXT)
|
||||
/* Vendor HCI support */
|
||||
u8_t vs_features[BT_DEV_VS_FEAT_MAX];
|
||||
u8_t vs_commands[BT_DEV_VS_CMDS_MAX];
|
||||
#endif
|
||||
|
||||
struct k_work init;
|
||||
|
||||
ATOMIC_DEFINE(flags, BT_DEV_NUM_FLAGS);
|
||||
|
||||
/* LE controller specific features */
|
||||
struct bt_dev_le le;
|
||||
|
||||
#if defined(CONFIG_BT_BREDR)
|
||||
/* BR/EDR controller specific features */
|
||||
struct bt_dev_br br;
|
||||
#endif
|
||||
|
||||
/* Number of commands controller can accept */
|
||||
struct k_sem ncmd_sem;
|
||||
|
||||
/* Last sent HCI command */
|
||||
struct net_buf *sent_cmd;
|
||||
|
||||
#if !defined(CONFIG_BT_RECV_IS_RX_THREAD)
|
||||
/* Queue for incoming HCI events & ACL data */
|
||||
struct k_fifo rx_queue;
|
||||
#endif
|
||||
|
||||
/* Queue for high priority HCI events which may unlock waiters
|
||||
* in other threads. Such events include Number of Completed
|
||||
* Packets, as well as the Command Complete/Status events.
|
||||
*/
|
||||
struct k_fifo rx_prio_queue;
|
||||
|
||||
/* Queue for outgoing HCI commands */
|
||||
struct k_fifo cmd_tx_queue;
|
||||
|
||||
/* Registered HCI driver */
|
||||
const struct bt_hci_driver *drv;
|
||||
|
||||
#if defined(CONFIG_BT_PRIVACY)
|
||||
/* Local Identity Resolving Key */
|
||||
u8_t irk[16];
|
||||
|
||||
/* Work used for RPA rotation */
|
||||
struct k_delayed_work rpa_update;
|
||||
#endif
|
||||
};
|
||||
|
||||
extern struct bt_dev bt_dev;
|
||||
extern const struct bt_storage *bt_storage;
|
||||
#if defined(CONFIG_BT_SMP) || defined(CONFIG_BT_BREDR)
|
||||
extern const struct bt_conn_auth_cb *bt_auth;
|
||||
#endif /* CONFIG_BT_SMP || CONFIG_BT_BREDR */
|
||||
|
||||
bool bt_le_conn_params_valid(const struct bt_le_conn_param *param);
|
||||
|
||||
struct net_buf *bt_hci_cmd_create(u16_t opcode, u8_t param_len);
|
||||
int bt_hci_cmd_send(u16_t opcode, struct net_buf *buf);
|
||||
int bt_hci_cmd_send_sync(u16_t opcode, struct net_buf *buf,
|
||||
struct net_buf **rsp);
|
||||
|
||||
int bt_le_scan_update(bool fast_scan);
|
||||
|
||||
bool bt_addr_le_is_bonded(const bt_addr_le_t *addr);
|
||||
|
||||
int bt_send(struct net_buf *buf);
|
||||
|
||||
u16_t bt_hci_get_cmd_opcode(struct net_buf *buf);
|
||||
|
||||
/* Don't require everyone to include keys.h */
|
||||
struct bt_keys;
|
||||
int bt_id_add(struct bt_keys *keys);
|
||||
int bt_id_del(struct bt_keys *keys);
|
||||
324
Living_SDK/kernel/protocols/bluetooth/host/hci_ecc.c
Normal file
324
Living_SDK/kernel/protocols/bluetooth/host/hci_ecc.c
Normal file
|
|
@ -0,0 +1,324 @@
|
|||
/**
|
||||
* @file hci_ecc.c
|
||||
* HCI ECC emulation
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2016 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <zephyr.h>
|
||||
#include <atomic.h>
|
||||
#include <misc/stack.h>
|
||||
#include <misc/byteorder.h>
|
||||
#include <tinycrypt/constants.h>
|
||||
#include <tinycrypt/utils.h>
|
||||
#include <tinycrypt/ecc.h>
|
||||
#include <tinycrypt/ecc_dh.h>
|
||||
|
||||
#include <bluetooth/bluetooth.h>
|
||||
#include <bluetooth/conn.h>
|
||||
#include <bluetooth/hci.h>
|
||||
#include <bluetooth/hci_driver.h>
|
||||
|
||||
#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_DEBUG_HCI_CORE)
|
||||
#include "common/log.h"
|
||||
|
||||
#include "hci_ecc.h"
|
||||
#ifdef CONFIG_BT_HCI_RAW
|
||||
#include <bluetooth/hci_raw.h>
|
||||
#include "hci_raw_internal.h"
|
||||
#else
|
||||
#include "hci_core.h"
|
||||
#endif
|
||||
|
||||
static struct k_thread ecc_thread_data;
|
||||
static BT_STACK_NOINIT(ecc_thread_stack, 1024);
|
||||
|
||||
/* based on Core Specification 4.2 Vol 3. Part H 2.3.5.6.1 */
|
||||
static const u32_t debug_private_key[8] = {
|
||||
0xcd3c1abd, 0x5899b8a6, 0xeb40b799, 0x4aff607b, 0xd2103f50, 0x74c9b3e3,
|
||||
0xa3c55f38, 0x3f49f6d4
|
||||
};
|
||||
|
||||
#if defined(CONFIG_BT_USE_DEBUG_KEYS)
|
||||
static const u8_t debug_public_key[64] = {
|
||||
0xe6, 0x9d, 0x35, 0x0e, 0x48, 0x01, 0x03, 0xcc, 0xdb, 0xfd, 0xf4, 0xac,
|
||||
0x11, 0x91, 0xf4, 0xef, 0xb9, 0xa5, 0xf9, 0xe9, 0xa7, 0x83, 0x2c, 0x5e,
|
||||
0x2c, 0xbe, 0x97, 0xf2, 0xd2, 0x03, 0xb0, 0x20, 0x8b, 0xd2, 0x89, 0x15,
|
||||
0xd0, 0x8e, 0x1c, 0x74, 0x24, 0x30, 0xed, 0x8f, 0xc2, 0x45, 0x63, 0x76,
|
||||
0x5c, 0x15, 0x52, 0x5a, 0xbf, 0x9a, 0x32, 0x63, 0x6d, 0xeb, 0x2a, 0x65,
|
||||
0x49, 0x9c, 0x80, 0xdc
|
||||
};
|
||||
#endif
|
||||
|
||||
enum {
|
||||
PENDING_PUB_KEY,
|
||||
PENDING_DHKEY,
|
||||
|
||||
/* Total number of flags - must be at the end of the enum */
|
||||
NUM_FLAGS,
|
||||
};
|
||||
|
||||
static ATOMIC_DEFINE(flags, NUM_FLAGS);
|
||||
|
||||
static K_SEM_DEFINE(cmd_sem, 0, 1);
|
||||
|
||||
static struct {
|
||||
u8_t private_key[32];
|
||||
|
||||
union {
|
||||
u8_t pk[64];
|
||||
u8_t dhkey[32];
|
||||
};
|
||||
} ecc;
|
||||
|
||||
static void send_cmd_status(u16_t opcode, u8_t status)
|
||||
{
|
||||
struct bt_hci_evt_cmd_status *evt;
|
||||
struct bt_hci_evt_hdr *hdr;
|
||||
struct net_buf *buf;
|
||||
|
||||
BT_DBG("opcode %x status %x", opcode, status);
|
||||
|
||||
buf = bt_buf_get_cmd_complete(K_FOREVER);
|
||||
bt_buf_set_type(buf, BT_BUF_EVT);
|
||||
|
||||
hdr = net_buf_add(buf, sizeof(*hdr));
|
||||
hdr->evt = BT_HCI_EVT_CMD_STATUS;
|
||||
hdr->len = sizeof(*evt);
|
||||
|
||||
evt = net_buf_add(buf, sizeof(*evt));
|
||||
evt->ncmd = 1;
|
||||
evt->opcode = sys_cpu_to_le16(opcode);
|
||||
evt->status = status;
|
||||
|
||||
bt_recv_prio(buf);
|
||||
}
|
||||
|
||||
static u8_t generate_keys(void)
|
||||
{
|
||||
#if !defined(CONFIG_BT_USE_DEBUG_KEYS)
|
||||
do {
|
||||
int rc;
|
||||
|
||||
rc = uECC_make_key(ecc.pk, ecc.private_key, &curve_secp256r1);
|
||||
if (rc == TC_CRYPTO_FAIL) {
|
||||
BT_ERR("Failed to create ECC public/private pair");
|
||||
return BT_HCI_ERR_UNSPECIFIED;
|
||||
}
|
||||
|
||||
/* make sure generated key isn't debug key */
|
||||
} while (memcmp(ecc.private_key, debug_private_key, 32) == 0);
|
||||
#else
|
||||
memcpy(&ecc.pk, debug_public_key, 64);
|
||||
memcpy(ecc.private_key, debug_private_key, 32);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void emulate_le_p256_public_key_cmd(void)
|
||||
{
|
||||
struct bt_hci_evt_le_p256_public_key_complete *evt;
|
||||
struct bt_hci_evt_le_meta_event *meta;
|
||||
struct bt_hci_evt_hdr *hdr;
|
||||
struct net_buf *buf;
|
||||
u8_t status;
|
||||
|
||||
BT_DBG("");
|
||||
|
||||
status = generate_keys();
|
||||
|
||||
buf = bt_buf_get_rx(BT_BUF_EVT, K_FOREVER);
|
||||
|
||||
hdr = net_buf_add(buf, sizeof(*hdr));
|
||||
hdr->evt = BT_HCI_EVT_LE_META_EVENT;
|
||||
hdr->len = sizeof(*meta) + sizeof(*evt);
|
||||
|
||||
meta = net_buf_add(buf, sizeof(*meta));
|
||||
meta->subevent = BT_HCI_EVT_LE_P256_PUBLIC_KEY_COMPLETE;
|
||||
|
||||
evt = net_buf_add(buf, sizeof(*evt));
|
||||
evt->status = status;
|
||||
|
||||
if (status) {
|
||||
memset(evt->key, 0, sizeof(evt->key));
|
||||
} else {
|
||||
/* Convert X and Y coordinates from big-endian (provided
|
||||
* by crypto API) to little endian HCI.
|
||||
*/
|
||||
sys_memcpy_swap(evt->key, ecc.pk, 32);
|
||||
sys_memcpy_swap(&evt->key[32], &ecc.pk[32], 32);
|
||||
}
|
||||
|
||||
atomic_clear_bit(flags, PENDING_PUB_KEY);
|
||||
|
||||
bt_recv(buf);
|
||||
}
|
||||
|
||||
static void emulate_le_generate_dhkey(void)
|
||||
{
|
||||
struct bt_hci_evt_le_generate_dhkey_complete *evt;
|
||||
struct bt_hci_evt_le_meta_event *meta;
|
||||
struct bt_hci_evt_hdr *hdr;
|
||||
struct net_buf *buf;
|
||||
int ret;
|
||||
|
||||
ret = uECC_valid_public_key(ecc.pk, &curve_secp256r1);
|
||||
if (ret < 0) {
|
||||
BT_ERR("public key is not valid (ret %d)", ret);
|
||||
ret = TC_CRYPTO_FAIL;
|
||||
} else {
|
||||
ret = uECC_shared_secret(ecc.pk, ecc.private_key, ecc.dhkey,
|
||||
&curve_secp256r1);
|
||||
}
|
||||
|
||||
buf = bt_buf_get_rx(BT_BUF_EVT, K_FOREVER);
|
||||
|
||||
hdr = net_buf_add(buf, sizeof(*hdr));
|
||||
hdr->evt = BT_HCI_EVT_LE_META_EVENT;
|
||||
hdr->len = sizeof(*meta) + sizeof(*evt);
|
||||
|
||||
meta = net_buf_add(buf, sizeof(*meta));
|
||||
meta->subevent = BT_HCI_EVT_LE_GENERATE_DHKEY_COMPLETE;
|
||||
|
||||
evt = net_buf_add(buf, sizeof(*evt));
|
||||
|
||||
if (ret == TC_CRYPTO_FAIL) {
|
||||
evt->status = BT_HCI_ERR_UNSPECIFIED;
|
||||
memset(evt->dhkey, 0, sizeof(evt->dhkey));
|
||||
} else {
|
||||
evt->status = 0;
|
||||
/* Convert from big-endian (provided by crypto API) to
|
||||
* little-endian HCI.
|
||||
*/
|
||||
sys_memcpy_swap(evt->dhkey, ecc.dhkey, sizeof(ecc.dhkey));
|
||||
}
|
||||
|
||||
atomic_clear_bit(flags, PENDING_DHKEY);
|
||||
|
||||
bt_recv(buf);
|
||||
}
|
||||
|
||||
static void ecc_thread(void *p1, void *p2, void *p3)
|
||||
{
|
||||
while (true) {
|
||||
k_sem_take(&cmd_sem, K_FOREVER);
|
||||
|
||||
if (atomic_test_bit(flags, PENDING_PUB_KEY)) {
|
||||
emulate_le_p256_public_key_cmd();
|
||||
} else if (atomic_test_bit(flags, PENDING_DHKEY)) {
|
||||
emulate_le_generate_dhkey();
|
||||
} else {
|
||||
__ASSERT(0, "Unhandled ECC command");
|
||||
}
|
||||
|
||||
STACK_ANALYZE("ecc stack", ecc_thread_stack);
|
||||
}
|
||||
}
|
||||
|
||||
static void clear_ecc_events(struct net_buf *buf)
|
||||
{
|
||||
struct bt_hci_cp_le_set_event_mask *cmd;
|
||||
|
||||
cmd = (void *)buf->data + sizeof(struct bt_hci_cmd_hdr);
|
||||
|
||||
/*
|
||||
* don't enable controller ECC events as those will be generated from
|
||||
* emulation code
|
||||
*/
|
||||
cmd->events[0] &= ~0x80; /* LE Read Local P-256 PKey Compl */
|
||||
cmd->events[1] &= ~0x01; /* LE Generate DHKey Compl Event */
|
||||
}
|
||||
|
||||
static void le_gen_dhkey(struct net_buf *buf)
|
||||
{
|
||||
struct bt_hci_cp_le_generate_dhkey *cmd;
|
||||
u8_t status;
|
||||
|
||||
if (atomic_test_bit(flags, PENDING_PUB_KEY)) {
|
||||
status = BT_HCI_ERR_CMD_DISALLOWED;
|
||||
goto send_status;
|
||||
}
|
||||
|
||||
if (buf->len < sizeof(struct bt_hci_cp_le_generate_dhkey)) {
|
||||
status = BT_HCI_ERR_INVALID_PARAM;
|
||||
goto send_status;
|
||||
}
|
||||
|
||||
if (atomic_test_and_set_bit(flags, PENDING_DHKEY)) {
|
||||
status = BT_HCI_ERR_CMD_DISALLOWED;
|
||||
goto send_status;
|
||||
}
|
||||
|
||||
cmd = (void *)buf->data;
|
||||
/* Convert X and Y coordinates from little-endian HCI to
|
||||
* big-endian (expected by the crypto API).
|
||||
*/
|
||||
sys_memcpy_swap(ecc.pk, cmd->key, 32);
|
||||
sys_memcpy_swap(&ecc.pk[32], &cmd->key[32], 32);
|
||||
k_sem_give(&cmd_sem);
|
||||
status = BT_HCI_ERR_SUCCESS;
|
||||
|
||||
send_status:
|
||||
net_buf_unref(buf);
|
||||
send_cmd_status(BT_HCI_OP_LE_GENERATE_DHKEY, status);
|
||||
}
|
||||
|
||||
static void le_p256_pub_key(struct net_buf *buf)
|
||||
{
|
||||
u8_t status;
|
||||
|
||||
net_buf_unref(buf);
|
||||
|
||||
if (atomic_test_bit(flags, PENDING_DHKEY)) {
|
||||
status = BT_HCI_ERR_CMD_DISALLOWED;
|
||||
} else if (atomic_test_and_set_bit(flags, PENDING_PUB_KEY)) {
|
||||
status = BT_HCI_ERR_CMD_DISALLOWED;
|
||||
} else {
|
||||
k_sem_give(&cmd_sem);
|
||||
status = BT_HCI_ERR_SUCCESS;
|
||||
}
|
||||
|
||||
send_cmd_status(BT_HCI_OP_LE_P256_PUBLIC_KEY, status);
|
||||
}
|
||||
|
||||
int bt_hci_ecc_send(struct net_buf *buf)
|
||||
{
|
||||
if (bt_buf_get_type(buf) == BT_BUF_CMD) {
|
||||
struct bt_hci_cmd_hdr *chdr = (void *)buf->data;
|
||||
|
||||
switch (sys_le16_to_cpu(chdr->opcode)) {
|
||||
case BT_HCI_OP_LE_P256_PUBLIC_KEY:
|
||||
net_buf_pull(buf, sizeof(*chdr));
|
||||
le_p256_pub_key(buf);
|
||||
return 0;
|
||||
case BT_HCI_OP_LE_GENERATE_DHKEY:
|
||||
net_buf_pull(buf, sizeof(*chdr));
|
||||
le_gen_dhkey(buf);
|
||||
return 0;
|
||||
case BT_HCI_OP_LE_SET_EVENT_MASK:
|
||||
clear_ecc_events(buf);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return bt_dev.drv->send(buf);
|
||||
}
|
||||
|
||||
int default_CSPRNG(u8_t *dst, unsigned int len)
|
||||
{
|
||||
return !bt_rand(dst, len);
|
||||
}
|
||||
|
||||
void bt_hci_ecc_init(void)
|
||||
{
|
||||
k_sem_init(&cmd_sem, 0, 1);
|
||||
k_thread_create(&ecc_thread_data, ecc_thread_stack,
|
||||
K_THREAD_STACK_SIZEOF(ecc_thread_stack), ecc_thread,
|
||||
NULL, NULL, NULL, 41, 0, K_NO_WAIT);
|
||||
}
|
||||
10
Living_SDK/kernel/protocols/bluetooth/host/hci_ecc.h
Normal file
10
Living_SDK/kernel/protocols/bluetooth/host/hci_ecc.h
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
/* hci_ecc.h - HCI ECC emulation */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2016 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
void bt_hci_ecc_init(void);
|
||||
int bt_hci_ecc_send(struct net_buf *buf);
|
||||
180
Living_SDK/kernel/protocols/bluetooth/host/keys.c
Normal file
180
Living_SDK/kernel/protocols/bluetooth/host/keys.c
Normal file
|
|
@ -0,0 +1,180 @@
|
|||
/* keys.c - Bluetooth key handling */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2015-2016 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <zephyr.h>
|
||||
#include <string.h>
|
||||
#include <atomic.h>
|
||||
#include <misc/util.h>
|
||||
|
||||
#include <bluetooth/bluetooth.h>
|
||||
#include <bluetooth/conn.h>
|
||||
#include <bluetooth/hci.h>
|
||||
|
||||
#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_DEBUG_KEYS)
|
||||
#include "common/log.h"
|
||||
|
||||
#include "common/rpa.h"
|
||||
#include "hci_core.h"
|
||||
#include "smp.h"
|
||||
#include "keys.h"
|
||||
|
||||
static struct bt_keys key_pool[CONFIG_BT_MAX_PAIRED];
|
||||
|
||||
struct bt_keys *bt_keys_get_addr(const bt_addr_le_t *addr)
|
||||
{
|
||||
struct bt_keys *keys;
|
||||
int i;
|
||||
|
||||
BT_DBG("%s", bt_addr_le_str(addr));
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(key_pool); i++) {
|
||||
keys = &key_pool[i];
|
||||
|
||||
if (!bt_addr_le_cmp(&keys->addr, addr)) {
|
||||
return keys;
|
||||
}
|
||||
|
||||
if (!bt_addr_le_cmp(&keys->addr, BT_ADDR_LE_ANY)) {
|
||||
bt_addr_le_copy(&keys->addr, addr);
|
||||
BT_DBG("created %p for %s", keys, bt_addr_le_str(addr));
|
||||
return keys;
|
||||
}
|
||||
}
|
||||
|
||||
BT_DBG("unable to create keys for %s", bt_addr_le_str(addr));
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void bt_keys_foreach(int type, void (*func)(struct bt_keys *keys))
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(key_pool); i++) {
|
||||
if ((key_pool[i].keys & type)) {
|
||||
func(&key_pool[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct bt_keys *bt_keys_find(int type, const bt_addr_le_t *addr)
|
||||
{
|
||||
int i;
|
||||
|
||||
BT_DBG("type %d %s", type, bt_addr_le_str(addr));
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(key_pool); i++) {
|
||||
if ((key_pool[i].keys & type) &&
|
||||
!bt_addr_le_cmp(&key_pool[i].addr, addr)) {
|
||||
return &key_pool[i];
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct bt_keys *bt_keys_get_type(int type, const bt_addr_le_t *addr)
|
||||
{
|
||||
struct bt_keys *keys;
|
||||
|
||||
BT_DBG("type %d %s", type, bt_addr_le_str(addr));
|
||||
|
||||
keys = bt_keys_find(type, addr);
|
||||
if (keys) {
|
||||
return keys;
|
||||
}
|
||||
|
||||
keys = bt_keys_get_addr(addr);
|
||||
if (!keys) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bt_keys_add_type(keys, type);
|
||||
|
||||
return keys;
|
||||
}
|
||||
|
||||
struct bt_keys *bt_keys_find_irk(const bt_addr_le_t *addr)
|
||||
{
|
||||
int i;
|
||||
|
||||
BT_DBG("%s", bt_addr_le_str(addr));
|
||||
|
||||
if (!bt_addr_le_is_rpa(addr)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(key_pool); i++) {
|
||||
if (!(key_pool[i].keys & BT_KEYS_IRK)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!bt_addr_cmp(&addr->a, &key_pool[i].irk.rpa)) {
|
||||
BT_DBG("cached RPA %s for %s",
|
||||
bt_addr_str(&key_pool[i].irk.rpa),
|
||||
bt_addr_le_str(&key_pool[i].addr));
|
||||
return &key_pool[i];
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(key_pool); i++) {
|
||||
if (!(key_pool[i].keys & BT_KEYS_IRK)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (bt_rpa_irk_matches(key_pool[i].irk.val, &addr->a)) {
|
||||
BT_DBG("RPA %s matches %s",
|
||||
bt_addr_str(&key_pool[i].irk.rpa),
|
||||
bt_addr_le_str(&key_pool[i].addr));
|
||||
|
||||
bt_addr_copy(&key_pool[i].irk.rpa, &addr->a);
|
||||
|
||||
return &key_pool[i];
|
||||
}
|
||||
}
|
||||
|
||||
BT_DBG("No IRK for %s", bt_addr_le_str(addr));
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct bt_keys *bt_keys_find_addr(const bt_addr_le_t *addr)
|
||||
{
|
||||
int i;
|
||||
|
||||
BT_DBG("%s", bt_addr_le_str(addr));
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(key_pool); i++) {
|
||||
if (!bt_addr_le_cmp(&key_pool[i].addr, addr)) {
|
||||
return &key_pool[i];
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void bt_keys_add_type(struct bt_keys *keys, int type)
|
||||
{
|
||||
keys->keys |= type;
|
||||
}
|
||||
|
||||
void bt_keys_clear(struct bt_keys *keys)
|
||||
{
|
||||
BT_DBG("keys for %s", bt_addr_le_str(&keys->addr));
|
||||
|
||||
if (keys->keys & BT_KEYS_IRK) {
|
||||
bt_id_del(keys);
|
||||
}
|
||||
|
||||
memset(keys, 0, sizeof(*keys));
|
||||
}
|
||||
|
||||
void bt_keys_clear_all(void)
|
||||
{
|
||||
bt_keys_foreach(BT_KEYS_ALL, bt_keys_clear);
|
||||
}
|
||||
94
Living_SDK/kernel/protocols/bluetooth/host/keys.h
Normal file
94
Living_SDK/kernel/protocols/bluetooth/host/keys.h
Normal file
|
|
@ -0,0 +1,94 @@
|
|||
/* keys.h - Bluetooth key handling */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2015-2016 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
enum {
|
||||
BT_KEYS_SLAVE_LTK = BIT(0),
|
||||
BT_KEYS_IRK = BIT(1),
|
||||
BT_KEYS_LTK = BIT(2),
|
||||
BT_KEYS_LOCAL_CSRK = BIT(3),
|
||||
BT_KEYS_REMOTE_CSRK = BIT(4),
|
||||
BT_KEYS_LTK_P256 = BIT(5),
|
||||
|
||||
BT_KEYS_ALL = (BT_KEYS_SLAVE_LTK | BT_KEYS_IRK | \
|
||||
BT_KEYS_LTK | BT_KEYS_LOCAL_CSRK | \
|
||||
BT_KEYS_REMOTE_CSRK | BT_KEYS_LTK_P256),
|
||||
};
|
||||
|
||||
enum {
|
||||
BT_KEYS_AUTHENTICATED,
|
||||
BT_KEYS_DEBUG,
|
||||
BT_KEYS_ID_PENDING_ADD,
|
||||
BT_KEYS_ID_PENDING_DEL,
|
||||
|
||||
/* Total number of flags - must be at the end of the enum */
|
||||
BT_KEYS_NUM_FLAGS,
|
||||
};
|
||||
|
||||
struct bt_ltk {
|
||||
u64_t rand;
|
||||
u16_t ediv;
|
||||
u8_t val[16];
|
||||
};
|
||||
|
||||
struct bt_irk {
|
||||
u8_t val[16];
|
||||
bt_addr_t rpa;
|
||||
};
|
||||
|
||||
struct bt_csrk {
|
||||
u8_t val[16];
|
||||
u32_t cnt;
|
||||
};
|
||||
|
||||
struct bt_keys {
|
||||
bt_addr_le_t addr;
|
||||
u8_t enc_size;
|
||||
ATOMIC_DEFINE(flags, BT_KEYS_NUM_FLAGS);
|
||||
u16_t keys;
|
||||
struct bt_ltk ltk;
|
||||
struct bt_irk irk;
|
||||
#if defined(CONFIG_BT_SIGNING)
|
||||
struct bt_csrk local_csrk;
|
||||
struct bt_csrk remote_csrk;
|
||||
#endif /* BT_SIGNING */
|
||||
#if !defined(CONFIG_BT_SMP_SC_ONLY)
|
||||
struct bt_ltk slave_ltk;
|
||||
#endif /* CONFIG_BT_SMP_SC_ONLY */
|
||||
};
|
||||
|
||||
void bt_keys_foreach(int type, void (*func)(struct bt_keys *keys));
|
||||
|
||||
struct bt_keys *bt_keys_get_addr(const bt_addr_le_t *addr);
|
||||
struct bt_keys *bt_keys_get_type(int type, const bt_addr_le_t *addr);
|
||||
struct bt_keys *bt_keys_find(int type, const bt_addr_le_t *addr);
|
||||
struct bt_keys *bt_keys_find_irk(const bt_addr_le_t *addr);
|
||||
struct bt_keys *bt_keys_find_addr(const bt_addr_le_t *addr);
|
||||
|
||||
void bt_keys_add_type(struct bt_keys *keys, int type);
|
||||
void bt_keys_clear(struct bt_keys *keys);
|
||||
void bt_keys_clear_all(void);
|
||||
|
||||
enum {
|
||||
BT_LINK_KEY_AUTHENTICATED,
|
||||
BT_LINK_KEY_DEBUG,
|
||||
BT_LINK_KEY_SC,
|
||||
|
||||
/* Total number of flags - must be at the end of the enum */
|
||||
BT_LINK_KEY_NUM_FLAGS,
|
||||
};
|
||||
|
||||
struct bt_keys_link_key {
|
||||
bt_addr_t addr;
|
||||
ATOMIC_DEFINE(flags, BT_LINK_KEY_NUM_FLAGS);
|
||||
u8_t val[16];
|
||||
};
|
||||
|
||||
struct bt_keys_link_key *bt_keys_get_link_key(const bt_addr_t *addr);
|
||||
struct bt_keys_link_key *bt_keys_find_link_key(const bt_addr_t *addr);
|
||||
void bt_keys_link_key_clear(struct bt_keys_link_key *link_key);
|
||||
void bt_keys_link_key_clear_addr(const bt_addr_t *addr);
|
||||
1692
Living_SDK/kernel/protocols/bluetooth/host/l2cap.c
Normal file
1692
Living_SDK/kernel/protocols/bluetooth/host/l2cap.c
Normal file
File diff suppressed because it is too large
Load diff
310
Living_SDK/kernel/protocols/bluetooth/host/l2cap_internal.h
Normal file
310
Living_SDK/kernel/protocols/bluetooth/host/l2cap_internal.h
Normal file
|
|
@ -0,0 +1,310 @@
|
|||
/** @file
|
||||
* @brief Internal APIs for Bluetooth L2CAP handling.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2015-2016 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <bluetooth/l2cap.h>
|
||||
|
||||
enum l2cap_conn_list_action {
|
||||
BT_L2CAP_CHAN_LOOKUP,
|
||||
BT_L2CAP_CHAN_DETACH,
|
||||
};
|
||||
|
||||
#define BT_L2CAP_CID_BR_SIG 0x0001
|
||||
#define BT_L2CAP_CID_ATT 0x0004
|
||||
#define BT_L2CAP_CID_LE_SIG 0x0005
|
||||
#define BT_L2CAP_CID_SMP 0x0006
|
||||
#define BT_L2CAP_CID_BR_SMP 0x0007
|
||||
|
||||
#define BT_L2CAP_PSM_RFCOMM 0x0003
|
||||
|
||||
struct bt_l2cap_hdr {
|
||||
u16_t len;
|
||||
u16_t cid;
|
||||
} __packed;
|
||||
|
||||
struct bt_l2cap_sig_hdr {
|
||||
u8_t code;
|
||||
u8_t ident;
|
||||
u16_t len;
|
||||
} __packed;
|
||||
|
||||
#define BT_L2CAP_REJ_NOT_UNDERSTOOD 0x0000
|
||||
#define BT_L2CAP_REJ_MTU_EXCEEDED 0x0001
|
||||
#define BT_L2CAP_REJ_INVALID_CID 0x0002
|
||||
|
||||
#define BT_L2CAP_CMD_REJECT 0x01
|
||||
struct bt_l2cap_cmd_reject {
|
||||
u16_t reason;
|
||||
u8_t data[0];
|
||||
} __packed;
|
||||
|
||||
struct bt_l2cap_cmd_reject_cid_data {
|
||||
u16_t scid;
|
||||
u16_t dcid;
|
||||
} __packed;
|
||||
|
||||
#define BT_L2CAP_CONN_REQ 0x02
|
||||
struct bt_l2cap_conn_req {
|
||||
u16_t psm;
|
||||
u16_t scid;
|
||||
} __packed;
|
||||
|
||||
/* command statuses in reposnse */
|
||||
#define BT_L2CAP_CS_NO_INFO 0x0000
|
||||
#define BT_L2CAP_CS_AUTHEN_PEND 0x0001
|
||||
|
||||
/* valid results in conn response on BR/EDR */
|
||||
#define BT_L2CAP_BR_SUCCESS 0x0000
|
||||
#define BT_L2CAP_BR_PENDING 0x0001
|
||||
#define BT_L2CAP_BR_ERR_PSM_NOT_SUPP 0x0002
|
||||
#define BT_L2CAP_BR_ERR_SEC_BLOCK 0x0003
|
||||
#define BT_L2CAP_BR_ERR_NO_RESOURCES 0x0004
|
||||
#define BT_L2CAP_BR_ERR_INVALID_SCID 0x0006
|
||||
#define BT_L2CAP_BR_ERR_SCID_IN_USE 0x0007
|
||||
|
||||
#define BT_L2CAP_CONN_RSP 0x03
|
||||
struct bt_l2cap_conn_rsp {
|
||||
u16_t dcid;
|
||||
u16_t scid;
|
||||
u16_t result;
|
||||
u16_t status;
|
||||
} __packed;
|
||||
|
||||
#define BT_L2CAP_CONF_SUCCESS 0x0000
|
||||
#define BT_L2CAP_CONF_UNACCEPT 0x0001
|
||||
#define BT_L2CAP_CONF_REJECT 0x0002
|
||||
|
||||
#define BT_L2CAP_CONF_REQ 0x04
|
||||
struct bt_l2cap_conf_req {
|
||||
u16_t dcid;
|
||||
u16_t flags;
|
||||
u8_t data[0];
|
||||
} __packed;
|
||||
|
||||
#define BT_L2CAP_CONF_RSP 0x05
|
||||
struct bt_l2cap_conf_rsp {
|
||||
u16_t scid;
|
||||
u16_t flags;
|
||||
u16_t result;
|
||||
u8_t data[0];
|
||||
} __packed;
|
||||
|
||||
/* Option type used by MTU config request data */
|
||||
#define BT_L2CAP_CONF_OPT_MTU 0x01
|
||||
/* Options bits selecting most significant bit (hint) in type field */
|
||||
#define BT_L2CAP_CONF_HINT 0x80
|
||||
#define BT_L2CAP_CONF_MASK 0x7f
|
||||
|
||||
struct bt_l2cap_conf_opt {
|
||||
u8_t type;
|
||||
u8_t len;
|
||||
u8_t data[0];
|
||||
} __packed;
|
||||
|
||||
#define BT_L2CAP_DISCONN_REQ 0x06
|
||||
struct bt_l2cap_disconn_req {
|
||||
u16_t dcid;
|
||||
u16_t scid;
|
||||
} __packed;
|
||||
|
||||
#define BT_L2CAP_DISCONN_RSP 0x07
|
||||
struct bt_l2cap_disconn_rsp {
|
||||
u16_t dcid;
|
||||
u16_t scid;
|
||||
} __packed;
|
||||
|
||||
#define BT_L2CAP_INFO_FEAT_MASK 0x0002
|
||||
#define BT_L2CAP_INFO_FIXED_CHAN 0x0003
|
||||
|
||||
#define BT_L2CAP_INFO_REQ 0x0a
|
||||
struct bt_l2cap_info_req {
|
||||
u16_t type;
|
||||
} __packed;
|
||||
|
||||
/* info result */
|
||||
#define BT_L2CAP_INFO_SUCCESS 0x0000
|
||||
#define BT_L2CAP_INFO_NOTSUPP 0x0001
|
||||
|
||||
#define BT_L2CAP_INFO_RSP 0x0b
|
||||
struct bt_l2cap_info_rsp {
|
||||
u16_t type;
|
||||
u16_t result;
|
||||
u8_t data[0];
|
||||
} __packed;
|
||||
|
||||
#define BT_L2CAP_CONN_PARAM_REQ 0x12
|
||||
struct bt_l2cap_conn_param_req {
|
||||
u16_t min_interval;
|
||||
u16_t max_interval;
|
||||
u16_t latency;
|
||||
u16_t timeout;
|
||||
} __packed;
|
||||
|
||||
#define BT_L2CAP_CONN_PARAM_ACCEPTED 0x0000
|
||||
#define BT_L2CAP_CONN_PARAM_REJECTED 0x0001
|
||||
|
||||
#define BT_L2CAP_CONN_PARAM_RSP 0x13
|
||||
struct bt_l2cap_conn_param_rsp {
|
||||
u16_t result;
|
||||
} __packed;
|
||||
|
||||
#define BT_L2CAP_LE_CONN_REQ 0x14
|
||||
struct bt_l2cap_le_conn_req {
|
||||
u16_t psm;
|
||||
u16_t scid;
|
||||
u16_t mtu;
|
||||
u16_t mps;
|
||||
u16_t credits;
|
||||
} __packed;
|
||||
|
||||
#define BT_L2CAP_SUCCESS 0x0000
|
||||
#define BT_L2CAP_PENDING 0x0001
|
||||
#define BT_L2CAP_ERR_PSM_NOT_SUPP 0x0002
|
||||
#define BT_L2CAP_ERR_SEC_BLOCK 0x0003
|
||||
#define BT_L2CAP_ERR_NO_RESOURCES 0x0004
|
||||
#define BT_L2CAP_ERR_AUTHENTICATION 0x0005
|
||||
#define BT_L2CAP_ERR_AUTHORIZATION 0x0006
|
||||
#define BT_L2CAP_ERR_KEY_SIZE 0x0007
|
||||
#define BT_L2CAP_ERR_ENCRYPTION 0x0008
|
||||
#define BT_L2CAP_ERR_INVALID_SCID 0x0009
|
||||
#define BT_L2CAP_ERR_SCID_IN_USE 0x000A
|
||||
|
||||
#define BT_L2CAP_LE_CONN_RSP 0x15
|
||||
struct bt_l2cap_le_conn_rsp {
|
||||
u16_t dcid;
|
||||
u16_t mtu;
|
||||
u16_t mps;
|
||||
u16_t credits;
|
||||
u16_t result;
|
||||
};
|
||||
|
||||
#define BT_L2CAP_LE_CREDITS 0x16
|
||||
struct bt_l2cap_le_credits {
|
||||
u16_t cid;
|
||||
u16_t credits;
|
||||
} __packed;
|
||||
|
||||
#define BT_L2CAP_SDU_HDR_LEN 2
|
||||
|
||||
#if defined(CONFIG_BT_HCI_ACL_FLOW_CONTROL)
|
||||
#define BT_L2CAP_RX_MTU CONFIG_BT_L2CAP_RX_MTU
|
||||
#else
|
||||
#define BT_L2CAP_RX_MTU (CONFIG_BT_RX_BUF_LEN - \
|
||||
BT_HCI_ACL_HDR_SIZE - BT_L2CAP_HDR_SIZE)
|
||||
#endif
|
||||
|
||||
struct bt_l2cap_fixed_chan {
|
||||
u16_t cid;
|
||||
int (*accept)(struct bt_conn *conn, struct bt_l2cap_chan **chan);
|
||||
sys_snode_t node;
|
||||
};
|
||||
|
||||
/* Register a fixed L2CAP channel for L2CAP */
|
||||
void bt_l2cap_le_fixed_chan_register(struct bt_l2cap_fixed_chan *chan);
|
||||
|
||||
/* Notify L2CAP channels of a new connection */
|
||||
void bt_l2cap_connected(struct bt_conn *conn);
|
||||
|
||||
/* Notify L2CAP channels of a disconnect event */
|
||||
void bt_l2cap_disconnected(struct bt_conn *conn);
|
||||
|
||||
/* Add channel to the connection */
|
||||
void bt_l2cap_chan_add(struct bt_conn *conn, struct bt_l2cap_chan *chan,
|
||||
bt_l2cap_chan_destroy_t destroy);
|
||||
|
||||
/* Remove channel from the connection */
|
||||
void bt_l2cap_chan_remove(struct bt_conn *conn, struct bt_l2cap_chan *chan);
|
||||
|
||||
/* Delete channel */
|
||||
void bt_l2cap_chan_del(struct bt_l2cap_chan *chan);
|
||||
|
||||
const char *bt_l2cap_chan_state_str(bt_l2cap_chan_state_t state);
|
||||
|
||||
#if defined(CONFIG_BT_DEBUG_L2CAP)
|
||||
void bt_l2cap_chan_set_state_debug(struct bt_l2cap_chan *chan,
|
||||
bt_l2cap_chan_state_t state,
|
||||
const char *func, int line);
|
||||
#define bt_l2cap_chan_set_state(_chan, _state) \
|
||||
bt_l2cap_chan_set_state_debug(_chan, _state, __func__, __LINE__)
|
||||
#else
|
||||
void bt_l2cap_chan_set_state(struct bt_l2cap_chan *chan,
|
||||
bt_l2cap_chan_state_t state);
|
||||
#endif /* CONFIG_BT_DEBUG_L2CAP */
|
||||
|
||||
/*
|
||||
* Notify L2CAP channels of a change in encryption state passing additionally
|
||||
* HCI status of performed security procedure.
|
||||
*/
|
||||
void bt_l2cap_encrypt_change(struct bt_conn *conn, u8_t hci_status);
|
||||
|
||||
/* Prepare an L2CAP PDU to be sent over a connection */
|
||||
struct net_buf *bt_l2cap_create_pdu(struct net_buf_pool *pool, size_t reserve);
|
||||
|
||||
/* Prepare a L2CAP Response PDU to be sent over a connection */
|
||||
struct net_buf *bt_l2cap_create_rsp(struct net_buf *buf, size_t reserve);
|
||||
|
||||
/* Send L2CAP PDU over a connection */
|
||||
void bt_l2cap_send_cb(struct bt_conn *conn, u16_t cid, struct net_buf *buf,
|
||||
bt_conn_tx_cb_t cb);
|
||||
|
||||
static inline void bt_l2cap_send(struct bt_conn *conn, u16_t cid,
|
||||
struct net_buf *buf)
|
||||
{
|
||||
bt_l2cap_send_cb(conn, cid, buf, NULL);
|
||||
}
|
||||
|
||||
/* Receive a new L2CAP PDU from a connection */
|
||||
void bt_l2cap_recv(struct bt_conn *conn, struct net_buf *buf);
|
||||
|
||||
/* Perform connection parameter update request */
|
||||
int bt_l2cap_update_conn_param(struct bt_conn *conn,
|
||||
const struct bt_le_conn_param *param);
|
||||
|
||||
/* Initialize L2CAP and supported channels */
|
||||
void bt_l2cap_init(void);
|
||||
|
||||
/* Lookup channel by Transmission CID */
|
||||
struct bt_l2cap_chan *bt_l2cap_le_lookup_tx_cid(struct bt_conn *conn,
|
||||
u16_t cid);
|
||||
|
||||
/* Lookup channel by Receiver CID */
|
||||
struct bt_l2cap_chan *bt_l2cap_le_lookup_rx_cid(struct bt_conn *conn,
|
||||
u16_t cid);
|
||||
|
||||
/* Initialize BR/EDR L2CAP signal layer */
|
||||
void bt_l2cap_br_init(void);
|
||||
|
||||
/* Register fixed channel */
|
||||
void bt_l2cap_br_fixed_chan_register(struct bt_l2cap_fixed_chan *chan);
|
||||
|
||||
/* Notify BR/EDR L2CAP channels about established new ACL connection */
|
||||
void bt_l2cap_br_connected(struct bt_conn *conn);
|
||||
|
||||
/* Lookup BR/EDR L2CAP channel by Receiver CID */
|
||||
struct bt_l2cap_chan *bt_l2cap_br_lookup_rx_cid(struct bt_conn *conn,
|
||||
u16_t cid);
|
||||
|
||||
/* Disconnects dynamic channel */
|
||||
int bt_l2cap_br_chan_disconnect(struct bt_l2cap_chan *chan);
|
||||
|
||||
/* Make connection to peer psm server */
|
||||
int bt_l2cap_br_chan_connect(struct bt_conn *conn, struct bt_l2cap_chan *chan,
|
||||
u16_t psm);
|
||||
|
||||
/* Send packet data to connected peer */
|
||||
int bt_l2cap_br_chan_send(struct bt_l2cap_chan *chan, struct net_buf *buf);
|
||||
|
||||
/*
|
||||
* Handle security level changed on link passing HCI status of performed
|
||||
* security procedure.
|
||||
*/
|
||||
void l2cap_br_encrypt_change(struct bt_conn *conn, u8_t hci_status);
|
||||
|
||||
/* Handle received data */
|
||||
void bt_l2cap_br_recv(struct bt_conn *conn, struct net_buf *buf);
|
||||
263
Living_SDK/kernel/protocols/bluetooth/host/monitor.c
Normal file
263
Living_SDK/kernel/protocols/bluetooth/host/monitor.c
Normal file
|
|
@ -0,0 +1,263 @@
|
|||
/** @file
|
||||
* @brief Custom logging over UART
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2016 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <zephyr/types.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <zephyr.h>
|
||||
#include <device.h>
|
||||
#include <init.h>
|
||||
#include <drivers/console/uart_pipe.h>
|
||||
#include <misc/byteorder.h>
|
||||
#include <misc/printk.h>
|
||||
#include <uart.h>
|
||||
|
||||
#include <bluetooth/buf.h>
|
||||
|
||||
#include "monitor.h"
|
||||
|
||||
/* This is the same default priority as for other console handlers,
|
||||
* except that we're not exporting it as a Kconfig variable until a
|
||||
* clear need arises.
|
||||
*/
|
||||
#define MONITOR_INIT_PRIORITY 60
|
||||
|
||||
static struct device *monitor_dev;
|
||||
|
||||
enum {
|
||||
BT_LOG_BUSY,
|
||||
BT_CONSOLE_BUSY,
|
||||
};
|
||||
|
||||
static atomic_t flags;
|
||||
|
||||
static struct {
|
||||
atomic_t cmd;
|
||||
atomic_t evt;
|
||||
atomic_t acl_tx;
|
||||
atomic_t acl_rx;
|
||||
#if defined(CONFIG_BT_BREDR)
|
||||
atomic_t sco_tx;
|
||||
atomic_t sco_rx;
|
||||
#endif
|
||||
atomic_t other;
|
||||
} drops;
|
||||
|
||||
extern int _prf(int (*func)(), void *dest,
|
||||
const char *format, va_list vargs);
|
||||
|
||||
static void monitor_send(const void *data, size_t len)
|
||||
{
|
||||
const u8_t *buf = data;
|
||||
|
||||
while (len--) {
|
||||
uart_poll_out(monitor_dev, *buf++);
|
||||
}
|
||||
}
|
||||
|
||||
static void encode_drops(struct bt_monitor_hdr *hdr, u8_t type,
|
||||
atomic_t *val)
|
||||
{
|
||||
atomic_val_t count;
|
||||
|
||||
count = atomic_set(val, 0);
|
||||
if (count) {
|
||||
hdr->ext[hdr->hdr_len++] = type;
|
||||
hdr->ext[hdr->hdr_len++] = min(count, 255);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void encode_hdr(struct bt_monitor_hdr *hdr, u16_t opcode,
|
||||
u16_t len)
|
||||
{
|
||||
struct bt_monitor_ts32 *ts;
|
||||
|
||||
hdr->opcode = sys_cpu_to_le16(opcode);
|
||||
hdr->flags = 0;
|
||||
|
||||
ts = (void *)hdr->ext;
|
||||
ts->type = BT_MONITOR_TS32;
|
||||
ts->ts32 = sys_cpu_to_le32(k_uptime_get() * 10);
|
||||
hdr->hdr_len = sizeof(*ts);
|
||||
|
||||
encode_drops(hdr, BT_MONITOR_COMMAND_DROPS, &drops.cmd);
|
||||
encode_drops(hdr, BT_MONITOR_EVENT_DROPS, &drops.evt);
|
||||
encode_drops(hdr, BT_MONITOR_ACL_TX_DROPS, &drops.acl_tx);
|
||||
encode_drops(hdr, BT_MONITOR_ACL_RX_DROPS, &drops.acl_rx);
|
||||
#if defined(CONFIG_BT_BREDR)
|
||||
encode_drops(hdr, BT_MONITOR_SCO_TX_DROPS, &drops.sco_tx);
|
||||
encode_drops(hdr, BT_MONITOR_SCO_RX_DROPS, &drops.sco_rx);
|
||||
#endif
|
||||
encode_drops(hdr, BT_MONITOR_OTHER_DROPS, &drops.other);
|
||||
|
||||
hdr->data_len = sys_cpu_to_le16(4 + hdr->hdr_len + len);
|
||||
}
|
||||
|
||||
static int log_out(int c, void *unused)
|
||||
{
|
||||
uart_poll_out(monitor_dev, c);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void drop_add(u16_t opcode)
|
||||
{
|
||||
switch (opcode) {
|
||||
case BT_MONITOR_COMMAND_PKT:
|
||||
atomic_inc(&drops.cmd);
|
||||
break;
|
||||
case BT_MONITOR_EVENT_PKT:
|
||||
atomic_inc(&drops.evt);
|
||||
break;
|
||||
case BT_MONITOR_ACL_TX_PKT:
|
||||
atomic_inc(&drops.acl_tx);
|
||||
break;
|
||||
case BT_MONITOR_ACL_RX_PKT:
|
||||
atomic_inc(&drops.acl_rx);
|
||||
break;
|
||||
#if defined(CONFIG_BT_BREDR)
|
||||
case BT_MONITOR_SCO_TX_PKT:
|
||||
atomic_inc(&drops.sco_tx);
|
||||
break;
|
||||
case BT_MONITOR_SCO_RX_PKT:
|
||||
atomic_inc(&drops.sco_rx);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
atomic_inc(&drops.other);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bt_log(int prio, const char *fmt, ...)
|
||||
{
|
||||
struct bt_monitor_user_logging log;
|
||||
struct bt_monitor_hdr hdr;
|
||||
const char id[] = "bt";
|
||||
va_list ap;
|
||||
int len;
|
||||
|
||||
va_start(ap, fmt);
|
||||
len = vsnprintk(NULL, 0, fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
if (len < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
log.priority = prio;
|
||||
log.ident_len = sizeof(id);
|
||||
|
||||
if (atomic_test_and_set_bit(&flags, BT_LOG_BUSY)) {
|
||||
drop_add(BT_MONITOR_USER_LOGGING);
|
||||
return;
|
||||
}
|
||||
|
||||
encode_hdr(&hdr, BT_MONITOR_USER_LOGGING,
|
||||
sizeof(log) + sizeof(id) + len + 1);
|
||||
|
||||
monitor_send(&hdr, BT_MONITOR_BASE_HDR_LEN + hdr.hdr_len);
|
||||
monitor_send(&log, sizeof(log));
|
||||
monitor_send(id, sizeof(id));
|
||||
|
||||
va_start(ap, fmt);
|
||||
_vprintk(log_out, NULL, fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
/* Terminate the string with null */
|
||||
uart_poll_out(monitor_dev, '\0');
|
||||
|
||||
atomic_clear_bit(&flags, BT_LOG_BUSY);
|
||||
}
|
||||
|
||||
void bt_monitor_send(u16_t opcode, const void *data, size_t len)
|
||||
{
|
||||
struct bt_monitor_hdr hdr;
|
||||
|
||||
if (atomic_test_and_set_bit(&flags, BT_LOG_BUSY)) {
|
||||
drop_add(opcode);
|
||||
return;
|
||||
}
|
||||
|
||||
encode_hdr(&hdr, opcode, len);
|
||||
|
||||
monitor_send(&hdr, BT_MONITOR_BASE_HDR_LEN + hdr.hdr_len);
|
||||
monitor_send(data, len);
|
||||
|
||||
atomic_clear_bit(&flags, BT_LOG_BUSY);
|
||||
}
|
||||
|
||||
void bt_monitor_new_index(u8_t type, u8_t bus, bt_addr_t *addr,
|
||||
const char *name)
|
||||
{
|
||||
struct bt_monitor_new_index pkt;
|
||||
|
||||
pkt.type = type;
|
||||
pkt.bus = bus;
|
||||
memcpy(pkt.bdaddr, addr, 6);
|
||||
strncpy(pkt.name, name, sizeof(pkt.name) - 1);
|
||||
pkt.name[sizeof(pkt.name) - 1] = '\0';
|
||||
|
||||
bt_monitor_send(BT_MONITOR_NEW_INDEX, &pkt, sizeof(pkt));
|
||||
}
|
||||
|
||||
#if !defined(CONFIG_UART_CONSOLE)
|
||||
static int monitor_console_out(int c)
|
||||
{
|
||||
static char buf[128];
|
||||
static size_t len;
|
||||
|
||||
if (atomic_test_and_set_bit(&flags, BT_CONSOLE_BUSY)) {
|
||||
return c;
|
||||
}
|
||||
|
||||
if (c != '\n' && len < sizeof(buf) - 1) {
|
||||
buf[len++] = c;
|
||||
atomic_clear_bit(&flags, BT_CONSOLE_BUSY);
|
||||
return c;
|
||||
}
|
||||
|
||||
buf[len++] = '\0';
|
||||
|
||||
bt_monitor_send(BT_MONITOR_SYSTEM_NOTE, buf, len);
|
||||
len = 0;
|
||||
|
||||
atomic_clear_bit(&flags, BT_CONSOLE_BUSY);
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
extern void __printk_hook_install(int (*fn)(int));
|
||||
extern void __stdout_hook_install(int (*fn)(int));
|
||||
#endif /* !CONFIG_UART_CONSOLE */
|
||||
|
||||
#if defined(CONFIG_HAS_DTS) && !defined(CONFIG_BT_MONITOR_ON_DEV_NAME)
|
||||
#define CONFIG_BT_MONITOR_ON_DEV_NAME CONFIG_UART_CONSOLE_ON_DEV_NAME
|
||||
#endif
|
||||
|
||||
static int bt_monitor_init(struct device *d)
|
||||
{
|
||||
ARG_UNUSED(d);
|
||||
|
||||
monitor_dev = device_get_binding(CONFIG_BT_MONITOR_ON_DEV_NAME);
|
||||
|
||||
#if defined(CONFIG_UART_INTERRUPT_DRIVEN)
|
||||
uart_irq_rx_disable(monitor_dev);
|
||||
uart_irq_tx_disable(monitor_dev);
|
||||
#endif
|
||||
|
||||
#if !defined(CONFIG_UART_CONSOLE)
|
||||
__printk_hook_install(monitor_console_out);
|
||||
__stdout_hook_install(monitor_console_out);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
SYS_INIT(bt_monitor_init, PRE_KERNEL_1, MONITOR_INIT_PRIORITY);
|
||||
102
Living_SDK/kernel/protocols/bluetooth/host/monitor.h
Normal file
102
Living_SDK/kernel/protocols/bluetooth/host/monitor.h
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
/** @file
|
||||
* @brief Custom monitor protocol logging over UART
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2016 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#if defined(CONFIG_BT_DEBUG_MONITOR)
|
||||
|
||||
#define BT_MONITOR_NEW_INDEX 0
|
||||
#define BT_MONITOR_DEL_INDEX 1
|
||||
#define BT_MONITOR_COMMAND_PKT 2
|
||||
#define BT_MONITOR_EVENT_PKT 3
|
||||
#define BT_MONITOR_ACL_TX_PKT 4
|
||||
#define BT_MONITOR_ACL_RX_PKT 5
|
||||
#define BT_MONITOR_SCO_TX_PKT 6
|
||||
#define BT_MONITOR_SCO_RX_PKT 7
|
||||
#define BT_MONITOR_OPEN_INDEX 8
|
||||
#define BT_MONITOR_CLOSE_INDEX 9
|
||||
#define BT_MONITOR_INDEX_INFO 10
|
||||
#define BT_MONITOR_VENDOR_DIAG 11
|
||||
#define BT_MONITOR_SYSTEM_NOTE 12
|
||||
#define BT_MONITOR_USER_LOGGING 13
|
||||
#define BT_MONITOR_NOP 255
|
||||
|
||||
#define BT_MONITOR_TYPE_PRIMARY 0
|
||||
#define BT_MONITOR_TYPE_AMP 1
|
||||
|
||||
/* Extended header types */
|
||||
#define BT_MONITOR_COMMAND_DROPS 1
|
||||
#define BT_MONITOR_EVENT_DROPS 2
|
||||
#define BT_MONITOR_ACL_RX_DROPS 3
|
||||
#define BT_MONITOR_ACL_TX_DROPS 4
|
||||
#define BT_MONITOR_SCO_RX_DROPS 5
|
||||
#define BT_MONITOR_SCO_TX_DROPS 6
|
||||
#define BT_MONITOR_OTHER_DROPS 7
|
||||
#define BT_MONITOR_TS32 8
|
||||
|
||||
#define BT_MONITOR_BASE_HDR_LEN 6
|
||||
|
||||
#if defined(CONFIG_BT_BREDR)
|
||||
#define BT_MONITOR_EXT_HDR_MAX 19
|
||||
#else
|
||||
#define BT_MONITOR_EXT_HDR_MAX 15
|
||||
#endif
|
||||
|
||||
struct bt_monitor_hdr {
|
||||
u16_t data_len;
|
||||
u16_t opcode;
|
||||
u8_t flags;
|
||||
u8_t hdr_len;
|
||||
|
||||
u8_t ext[BT_MONITOR_EXT_HDR_MAX];
|
||||
} __packed;
|
||||
|
||||
struct bt_monitor_ts32 {
|
||||
u8_t type;
|
||||
u32_t ts32;
|
||||
} __packed;
|
||||
|
||||
struct bt_monitor_new_index {
|
||||
u8_t type;
|
||||
u8_t bus;
|
||||
u8_t bdaddr[6];
|
||||
char name[8];
|
||||
} __packed;
|
||||
|
||||
struct bt_monitor_user_logging {
|
||||
u8_t priority;
|
||||
u8_t ident_len;
|
||||
} __packed;
|
||||
|
||||
static inline u8_t bt_monitor_opcode(struct net_buf *buf)
|
||||
{
|
||||
switch (bt_buf_get_type(buf)) {
|
||||
case BT_BUF_CMD:
|
||||
return BT_MONITOR_COMMAND_PKT;
|
||||
case BT_BUF_EVT:
|
||||
return BT_MONITOR_EVENT_PKT;
|
||||
case BT_BUF_ACL_OUT:
|
||||
return BT_MONITOR_ACL_TX_PKT;
|
||||
case BT_BUF_ACL_IN:
|
||||
return BT_MONITOR_ACL_RX_PKT;
|
||||
default:
|
||||
return BT_MONITOR_NOP;
|
||||
}
|
||||
}
|
||||
|
||||
void bt_monitor_send(u16_t opcode, const void *data, size_t len);
|
||||
|
||||
void bt_monitor_new_index(u8_t type, u8_t bus, bt_addr_t *addr,
|
||||
const char *name);
|
||||
|
||||
#else /* !CONFIG_BT_DEBUG_MONITOR */
|
||||
|
||||
#define bt_monitor_send(opcode, data, len)
|
||||
#define bt_monitor_new_index(type, bus, addr, name)
|
||||
|
||||
#endif
|
||||
4488
Living_SDK/kernel/protocols/bluetooth/host/smp.c
Normal file
4488
Living_SDK/kernel/protocols/bluetooth/host/smp.c
Normal file
File diff suppressed because it is too large
Load diff
155
Living_SDK/kernel/protocols/bluetooth/host/smp.h
Normal file
155
Living_SDK/kernel/protocols/bluetooth/host/smp.h
Normal file
|
|
@ -0,0 +1,155 @@
|
|||
/**
|
||||
* @file smp.h
|
||||
* Security Manager Protocol implementation header
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2015-2016 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
struct bt_smp_hdr {
|
||||
u8_t code;
|
||||
} __packed;
|
||||
|
||||
#define BT_SMP_ERR_PASSKEY_ENTRY_FAILED 0x01
|
||||
#define BT_SMP_ERR_OOB_NOT_AVAIL 0x02
|
||||
#define BT_SMP_ERR_AUTH_REQUIREMENTS 0x03
|
||||
#define BT_SMP_ERR_CONFIRM_FAILED 0x04
|
||||
#define BT_SMP_ERR_PAIRING_NOTSUPP 0x05
|
||||
#define BT_SMP_ERR_ENC_KEY_SIZE 0x06
|
||||
#define BT_SMP_ERR_CMD_NOTSUPP 0x07
|
||||
#define BT_SMP_ERR_UNSPECIFIED 0x08
|
||||
#define BT_SMP_ERR_REPEATED_ATTEMPTS 0x09
|
||||
#define BT_SMP_ERR_INVALID_PARAMS 0x0a
|
||||
#define BT_SMP_ERR_DHKEY_CHECK_FAILED 0x0b
|
||||
#define BT_SMP_ERR_NUMERIC_COMP_FAILED 0x0c
|
||||
#define BT_SMP_ERR_BREDR_PAIRING_IN_PROGRESS 0x0d
|
||||
#define BT_SMP_ERR_CROSS_TRANSP_NOT_ALLOWED 0x0e
|
||||
|
||||
#define BT_SMP_IO_DISPLAY_ONLY 0x00
|
||||
#define BT_SMP_IO_DISPLAY_YESNO 0x01
|
||||
#define BT_SMP_IO_KEYBOARD_ONLY 0x02
|
||||
#define BT_SMP_IO_NO_INPUT_OUTPUT 0x03
|
||||
#define BT_SMP_IO_KEYBOARD_DISPLAY 0x04
|
||||
|
||||
#define BT_SMP_OOB_NOT_PRESENT 0x00
|
||||
#define BT_SMP_OOB_PRESENT 0x01
|
||||
|
||||
#define BT_SMP_MIN_ENC_KEY_SIZE 7
|
||||
#define BT_SMP_MAX_ENC_KEY_SIZE 16
|
||||
|
||||
#define BT_SMP_DIST_ENC_KEY 0x01
|
||||
#define BT_SMP_DIST_ID_KEY 0x02
|
||||
#define BT_SMP_DIST_SIGN 0x04
|
||||
#define BT_SMP_DIST_LINK_KEY 0x08
|
||||
|
||||
#define BT_SMP_DIST_MASK 0x0f
|
||||
|
||||
#define BT_SMP_AUTH_NONE 0x00
|
||||
#define BT_SMP_AUTH_BONDING 0x01
|
||||
#define BT_SMP_AUTH_MITM 0x04
|
||||
#define BT_SMP_AUTH_SC 0x08
|
||||
#define BT_SMP_AUTH_KEYPRESS 0x10
|
||||
#define BT_SMP_AUTH_CT2 0x20
|
||||
|
||||
#define BT_SMP_CMD_PAIRING_REQ 0x01
|
||||
#define BT_SMP_CMD_PAIRING_RSP 0x02
|
||||
struct bt_smp_pairing {
|
||||
u8_t io_capability;
|
||||
u8_t oob_flag;
|
||||
u8_t auth_req;
|
||||
u8_t max_key_size;
|
||||
u8_t init_key_dist;
|
||||
u8_t resp_key_dist;
|
||||
} __packed;
|
||||
|
||||
#define BT_SMP_CMD_PAIRING_CONFIRM 0x03
|
||||
struct bt_smp_pairing_confirm {
|
||||
u8_t val[16];
|
||||
} __packed;
|
||||
|
||||
#define BT_SMP_CMD_PAIRING_RANDOM 0x04
|
||||
struct bt_smp_pairing_random {
|
||||
u8_t val[16];
|
||||
} __packed;
|
||||
|
||||
#define BT_SMP_CMD_PAIRING_FAIL 0x05
|
||||
struct bt_smp_pairing_fail {
|
||||
u8_t reason;
|
||||
} __packed;
|
||||
|
||||
#define BT_SMP_CMD_ENCRYPT_INFO 0x06
|
||||
struct bt_smp_encrypt_info {
|
||||
u8_t ltk[16];
|
||||
} __packed;
|
||||
|
||||
#define BT_SMP_CMD_MASTER_IDENT 0x07
|
||||
struct bt_smp_master_ident {
|
||||
u16_t ediv;
|
||||
u64_t rand;
|
||||
} __packed;
|
||||
|
||||
#define BT_SMP_CMD_IDENT_INFO 0x08
|
||||
struct bt_smp_ident_info {
|
||||
u8_t irk[16];
|
||||
} __packed;
|
||||
|
||||
#define BT_SMP_CMD_IDENT_ADDR_INFO 0x09
|
||||
struct bt_smp_ident_addr_info {
|
||||
bt_addr_le_t addr;
|
||||
} __packed;
|
||||
|
||||
#define BT_SMP_CMD_SIGNING_INFO 0x0a
|
||||
struct bt_smp_signing_info {
|
||||
u8_t csrk[16];
|
||||
} __packed;
|
||||
|
||||
#define BT_SMP_CMD_SECURITY_REQUEST 0x0b
|
||||
struct bt_smp_security_request {
|
||||
u8_t auth_req;
|
||||
} __packed;
|
||||
|
||||
#define BT_SMP_CMD_PUBLIC_KEY 0x0c
|
||||
struct bt_smp_public_key {
|
||||
u8_t x[32];
|
||||
u8_t y[32];
|
||||
} __packed;
|
||||
|
||||
#define BT_SMP_DHKEY_CHECK 0x0d
|
||||
struct bt_smp_dhkey_check {
|
||||
u8_t e[16];
|
||||
} __packed;
|
||||
|
||||
int bt_smp_send_pairing_req(struct bt_conn *conn);
|
||||
int bt_smp_send_security_req(struct bt_conn *conn);
|
||||
void bt_smp_update_keys(struct bt_conn *conn);
|
||||
bool bt_smp_get_tk(struct bt_conn *conn, u8_t *tk);
|
||||
|
||||
int bt_smp_br_send_pairing_req(struct bt_conn *conn);
|
||||
|
||||
int bt_smp_init(void);
|
||||
|
||||
int bt_smp_auth_passkey_entry(struct bt_conn *conn, unsigned int passkey);
|
||||
int bt_smp_auth_passkey_confirm(struct bt_conn *conn);
|
||||
int bt_smp_auth_pairing_confirm(struct bt_conn *conn);
|
||||
int bt_smp_auth_cancel(struct bt_conn *conn);
|
||||
|
||||
/** brief Verify signed message
|
||||
*
|
||||
* @param conn Bluetooth connection
|
||||
* @param buf received packet buffer with message and signature
|
||||
*
|
||||
* @return 0 in success, error code otherwise
|
||||
*/
|
||||
int bt_smp_sign_verify(struct bt_conn *conn, struct net_buf *buf);
|
||||
|
||||
/** brief Sign message
|
||||
*
|
||||
* @param conn Bluetooth connection
|
||||
* @param buf message buffer
|
||||
*
|
||||
* @return 0 in success, error code otherwise
|
||||
*/
|
||||
int bt_smp_sign(struct bt_conn *conn, struct net_buf *buf);
|
||||
103
Living_SDK/kernel/protocols/bluetooth/host/smp_null.c
Normal file
103
Living_SDK/kernel/protocols/bluetooth/host/smp_null.c
Normal file
|
|
@ -0,0 +1,103 @@
|
|||
/**
|
||||
* @file smp_null.c
|
||||
* Security Manager Protocol stub
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2015-2016 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <zephyr.h>
|
||||
#include <errno.h>
|
||||
#include <atomic.h>
|
||||
#include <misc/util.h>
|
||||
|
||||
#include <bluetooth/bluetooth.h>
|
||||
#include <bluetooth/conn.h>
|
||||
#include <bluetooth/buf.h>
|
||||
|
||||
#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_DEBUG_HCI_CORE)
|
||||
#include "common/log.h"
|
||||
|
||||
#include "hci_core.h"
|
||||
#include "conn_internal.h"
|
||||
#include "l2cap_internal.h"
|
||||
#include "smp.h"
|
||||
|
||||
static struct bt_l2cap_le_chan bt_smp_pool[CONFIG_BT_MAX_CONN];
|
||||
|
||||
int bt_smp_sign_verify(struct bt_conn *conn, struct net_buf *buf)
|
||||
{
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
int bt_smp_sign(struct bt_conn *conn, struct net_buf *buf)
|
||||
{
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
static void bt_smp_recv(struct bt_l2cap_chan *chan, struct net_buf *buf)
|
||||
{
|
||||
struct bt_conn *conn = chan->conn;
|
||||
struct bt_smp_pairing_fail *rsp;
|
||||
struct bt_smp_hdr *hdr;
|
||||
|
||||
/* If a device does not support pairing then it shall respond with
|
||||
* a Pairing Failed command with the reason set to "Pairing Not
|
||||
* Supported" when any command is received.
|
||||
* Core Specification Vol. 3, Part H, 3.3
|
||||
*/
|
||||
|
||||
buf = bt_l2cap_create_pdu(NULL, 0);
|
||||
/* NULL is not a possible return due to K_FOREVER */
|
||||
|
||||
hdr = net_buf_add(buf, sizeof(*hdr));
|
||||
hdr->code = BT_SMP_CMD_PAIRING_FAIL;
|
||||
|
||||
rsp = net_buf_add(buf, sizeof(*rsp));
|
||||
rsp->reason = BT_SMP_ERR_PAIRING_NOTSUPP;
|
||||
|
||||
bt_l2cap_send(conn, BT_L2CAP_CID_SMP, buf);
|
||||
}
|
||||
|
||||
static int bt_smp_accept(struct bt_conn *conn, struct bt_l2cap_chan **chan)
|
||||
{
|
||||
int i;
|
||||
static struct bt_l2cap_chan_ops ops = {
|
||||
.recv = bt_smp_recv,
|
||||
};
|
||||
|
||||
BT_DBG("conn %p handle %u", conn, conn->handle);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(bt_smp_pool); i++) {
|
||||
struct bt_l2cap_le_chan *smp = &bt_smp_pool[i];
|
||||
|
||||
if (smp->chan.conn) {
|
||||
continue;
|
||||
}
|
||||
|
||||
smp->chan.ops = &ops;
|
||||
|
||||
*chan = &smp->chan;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
BT_ERR("No available SMP context for conn %p", conn);
|
||||
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
int bt_smp_init(void)
|
||||
{
|
||||
static struct bt_l2cap_fixed_chan chan = {
|
||||
.cid = BT_L2CAP_CID_SMP,
|
||||
.accept = bt_smp_accept,
|
||||
};
|
||||
|
||||
bt_l2cap_le_fixed_chan_register(&chan);
|
||||
|
||||
return 0;
|
||||
}
|
||||
229
Living_SDK/kernel/protocols/bluetooth/host/storage.c
Normal file
229
Living_SDK/kernel/protocols/bluetooth/host/storage.c
Normal file
|
|
@ -0,0 +1,229 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <misc/printk.h>
|
||||
|
||||
#include <zephyr.h>
|
||||
#include <init.h>
|
||||
#include <fs.h>
|
||||
|
||||
#include <bluetooth/bluetooth.h>
|
||||
#include <bluetooth/storage.h>
|
||||
|
||||
#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_DEBUG_HCI_CORE)
|
||||
#include "common/log.h"
|
||||
|
||||
#define STORAGE_ROOT "/bt"
|
||||
|
||||
/* Required file name length for full storage support. If the maximum
|
||||
* file name length supported by the chosen file system is less than
|
||||
* this value, then only local keys are supported (/bt/abcd).
|
||||
*/
|
||||
#define STORAGE_FILE_NAME_LEN 13
|
||||
|
||||
#if MAX_FILE_NAME >= STORAGE_FILE_NAME_LEN
|
||||
/* /bt/aabbccddeeff0/abcd */
|
||||
#define STORAGE_PATH_MAX 23
|
||||
#else
|
||||
/* /bt/abcd */
|
||||
#define STORAGE_PATH_MAX 9
|
||||
#endif
|
||||
|
||||
enum storage_access {
|
||||
STORAGE_READ,
|
||||
STORAGE_WRITE
|
||||
};
|
||||
|
||||
static int storage_open(const bt_addr_le_t *addr, u16_t key,
|
||||
enum storage_access access, fs_file_t *file)
|
||||
{
|
||||
char path[STORAGE_PATH_MAX];
|
||||
|
||||
if (addr) {
|
||||
#if MAX_FILE_NAME >= STORAGE_FILE_NAME_LEN
|
||||
int len;
|
||||
|
||||
len = snprintk(path, sizeof(path),
|
||||
STORAGE_ROOT "/%02X%02X%02X%02X%02X%02X%u",
|
||||
addr->a.val[5], addr->a.val[4], addr->a.val[3],
|
||||
addr->a.val[2], addr->a.val[1], addr->a.val[0],
|
||||
addr->type);
|
||||
|
||||
/* Create the subdirectory if necessary */
|
||||
if (access == STORAGE_WRITE) {
|
||||
struct fs_dirent entry;
|
||||
int err;
|
||||
|
||||
err = fs_stat(path, &entry);
|
||||
if (err) {
|
||||
err = fs_mkdir(path);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
snprintk(path + len, sizeof(path) - len, "/%04x", key);
|
||||
#else
|
||||
return -ENAMETOOLONG;
|
||||
#endif
|
||||
} else {
|
||||
snprintk(path, sizeof(path), STORAGE_ROOT "/%04x", key);
|
||||
}
|
||||
|
||||
return fs_open(file, path);
|
||||
}
|
||||
|
||||
static ssize_t storage_read(const bt_addr_le_t *addr, u16_t key, void *data,
|
||||
size_t length)
|
||||
{
|
||||
fs_file_t file;
|
||||
ssize_t ret;
|
||||
|
||||
ret = storage_open(addr, key, STORAGE_READ, &file);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = fs_read(&file, data, length);
|
||||
fs_close(&file);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t storage_write(const bt_addr_le_t *addr, u16_t key,
|
||||
const void *data, size_t length)
|
||||
{
|
||||
fs_file_t file;
|
||||
ssize_t ret;
|
||||
|
||||
ret = storage_open(addr, key, STORAGE_WRITE, &file);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = fs_write(&file, data, length);
|
||||
fs_close(&file);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int unlink_recursive(char path[STORAGE_PATH_MAX])
|
||||
{
|
||||
size_t path_len;
|
||||
fs_dir_t dir;
|
||||
int err;
|
||||
|
||||
err = fs_opendir(&dir, path);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
/* We calculate this up-front so we can keep reusing the same
|
||||
* buffer for the path when recursing.
|
||||
*/
|
||||
path_len = strlen(path);
|
||||
|
||||
while (1) {
|
||||
struct fs_dirent entry;
|
||||
|
||||
err = fs_readdir(&dir, &entry);
|
||||
if (err) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (entry.name[0] == '\0') {
|
||||
break;
|
||||
}
|
||||
|
||||
snprintk(path + path_len, STORAGE_PATH_MAX - path_len, "/%s",
|
||||
entry.name);
|
||||
|
||||
if (entry.type == FS_DIR_ENTRY_DIR) {
|
||||
err = unlink_recursive(path);
|
||||
} else {
|
||||
err = fs_unlink(path);
|
||||
}
|
||||
|
||||
if (err) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
fs_closedir(&dir);
|
||||
|
||||
/* Return to the original value */
|
||||
path[path_len] = '\0';
|
||||
|
||||
fs_unlink(path);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int storage_clear(const bt_addr_le_t *addr)
|
||||
{
|
||||
char path[STORAGE_PATH_MAX];
|
||||
int err;
|
||||
|
||||
if (addr) {
|
||||
#if MAX_FILE_NAME >= STORAGE_FILE_NAME_LEN
|
||||
snprintk(path, STORAGE_PATH_MAX,
|
||||
STORAGE_ROOT "/%02X%02X%02X%02X%02X%02X%u",
|
||||
addr->a.val[5], addr->a.val[4], addr->a.val[3],
|
||||
addr->a.val[2], addr->a.val[1], addr->a.val[0],
|
||||
addr->type);
|
||||
|
||||
return unlink_recursive(path);
|
||||
#else
|
||||
return -ENAMETOOLONG;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* unlink_recursive() uses the given path as a buffer for
|
||||
* constructing sub-paths, so we can't give it a string literal
|
||||
* such as STORAGE_ROOT directly.
|
||||
*/
|
||||
strcpy(path, STORAGE_ROOT);
|
||||
|
||||
err = unlink_recursive(path);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
return fs_mkdir(STORAGE_ROOT);
|
||||
}
|
||||
|
||||
static int storage_init(struct device *unused)
|
||||
{
|
||||
static const struct bt_storage storage = {
|
||||
.read = storage_read,
|
||||
.write = storage_write,
|
||||
.clear = storage_clear
|
||||
};
|
||||
struct fs_dirent entry;
|
||||
int err;
|
||||
|
||||
err = fs_stat(STORAGE_ROOT, &entry);
|
||||
if (err) {
|
||||
BT_WARN("%s doesn't seem to exist (err %d). Creating it.",
|
||||
STORAGE_ROOT, err);
|
||||
|
||||
err = fs_mkdir(STORAGE_ROOT);
|
||||
if (err) {
|
||||
BT_ERR("Unable to create %s (err %d)",
|
||||
STORAGE_ROOT, err);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
bt_storage_register(&storage);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
SYS_INIT(storage_init, APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);
|
||||
120
Living_SDK/kernel/protocols/bluetooth/host/uuid.c
Normal file
120
Living_SDK/kernel/protocols/bluetooth/host/uuid.c
Normal file
|
|
@ -0,0 +1,120 @@
|
|||
/* uuid.c - Bluetooth UUID handling */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2015-2016 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <misc/byteorder.h>
|
||||
#include <misc/printk.h>
|
||||
|
||||
#include <bluetooth/uuid.h>
|
||||
|
||||
#define UUID_16_BASE_OFFSET 12
|
||||
|
||||
/* TODO: Decide whether to continue using BLE format or switch to RFC 4122 */
|
||||
|
||||
/* Base UUID : 0000[0000]-0000-1000-8000-00805F9B34FB ->
|
||||
* { 0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80,
|
||||
* 0x00, 0x10, 0x00, 0x00, [0x00, 0x00], 0x00, 0x00 }
|
||||
* 0x2800 : 0000[2800]-0000-1000-8000-00805F9B34FB ->
|
||||
* { 0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80,
|
||||
* 0x00, 0x10, 0x00, 0x00, [0x00, 0x28], 0x00, 0x00 }
|
||||
* little endian 0x2800 : [00 28] -> no swapping required
|
||||
* big endian 0x2800 : [28 00] -> swapping required
|
||||
*/
|
||||
static const struct bt_uuid_128 uuid128_base = {
|
||||
.uuid.type = BT_UUID_TYPE_128,
|
||||
.val = { 0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80,
|
||||
0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
|
||||
};
|
||||
|
||||
static void uuid_to_uuid128(const struct bt_uuid *src, struct bt_uuid_128 *dst)
|
||||
{
|
||||
switch (src->type) {
|
||||
case BT_UUID_TYPE_16:
|
||||
*dst = uuid128_base;
|
||||
sys_put_le16(BT_UUID_16(src)->val,
|
||||
&dst->val[UUID_16_BASE_OFFSET]);
|
||||
return;
|
||||
case BT_UUID_TYPE_32:
|
||||
*dst = uuid128_base;
|
||||
sys_put_le32(BT_UUID_32(src)->val,
|
||||
&dst->val[UUID_16_BASE_OFFSET]);
|
||||
return;
|
||||
case BT_UUID_TYPE_128:
|
||||
memcpy(dst, src, sizeof(*dst));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static int uuid128_cmp(const struct bt_uuid *u1, const struct bt_uuid *u2)
|
||||
{
|
||||
struct bt_uuid_128 uuid1, uuid2;
|
||||
|
||||
uuid_to_uuid128(u1, &uuid1);
|
||||
uuid_to_uuid128(u2, &uuid2);
|
||||
|
||||
return memcmp(uuid1.val, uuid2.val, 16);
|
||||
}
|
||||
|
||||
int bt_uuid_cmp(const struct bt_uuid *u1, const struct bt_uuid *u2)
|
||||
{
|
||||
/* Convert to 128 bit if types don't match */
|
||||
if (u1->type != u2->type)
|
||||
return uuid128_cmp(u1, u2);
|
||||
|
||||
switch (u1->type) {
|
||||
case BT_UUID_TYPE_16:
|
||||
return (int)BT_UUID_16(u1)->val - (int)BT_UUID_16(u2)->val;
|
||||
case BT_UUID_TYPE_32:
|
||||
return (int)BT_UUID_32(u1)->val - (int)BT_UUID_32(u2)->val;
|
||||
case BT_UUID_TYPE_128:
|
||||
return memcmp(BT_UUID_128(u1)->val, BT_UUID_128(u2)->val, 16);
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_BT_DEBUG)
|
||||
void bt_uuid_to_str(const struct bt_uuid *uuid, char *str, size_t len)
|
||||
{
|
||||
u32_t tmp1, tmp5;
|
||||
u16_t tmp0, tmp2, tmp3, tmp4;
|
||||
|
||||
switch (uuid->type) {
|
||||
case BT_UUID_TYPE_16:
|
||||
snprintk(str, len, "%04x", BT_UUID_16(uuid)->val);
|
||||
break;
|
||||
case BT_UUID_TYPE_32:
|
||||
snprintk(str, len, "%04x", BT_UUID_32(uuid)->val);
|
||||
break;
|
||||
case BT_UUID_TYPE_128:
|
||||
memcpy(&tmp0, &BT_UUID_128(uuid)->val[0], sizeof(tmp0));
|
||||
memcpy(&tmp1, &BT_UUID_128(uuid)->val[2], sizeof(tmp1));
|
||||
memcpy(&tmp2, &BT_UUID_128(uuid)->val[6], sizeof(tmp2));
|
||||
memcpy(&tmp3, &BT_UUID_128(uuid)->val[8], sizeof(tmp3));
|
||||
memcpy(&tmp4, &BT_UUID_128(uuid)->val[10], sizeof(tmp4));
|
||||
memcpy(&tmp5, &BT_UUID_128(uuid)->val[12], sizeof(tmp5));
|
||||
|
||||
snprintk(str, len, "%08x-%04x-%04x-%04x-%08x%04x",
|
||||
tmp5, tmp4, tmp3, tmp2, tmp1, tmp0);
|
||||
break;
|
||||
default:
|
||||
memset(str, 0, len);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
const char *bt_uuid_str(const struct bt_uuid *uuid)
|
||||
{
|
||||
static char str[37];
|
||||
|
||||
bt_uuid_to_str(uuid, str, sizeof(str));
|
||||
|
||||
return str;
|
||||
}
|
||||
#endif /* CONFIG_BT_DEBUG */
|
||||
Loading…
Add table
Add a link
Reference in a new issue