Compare commits

...

57 Commits

Author SHA1 Message Date
Mariusz Skamra
ec4e86f5cc Bluetooth: controller: Workaround CPR procedure collision at CPU instant
This is a workaround for IOP issue, where peer rejects LLCP Slave
Connection Parameter Request with LMP Error Transaction Collision
error code even if previous request is complete at the instant.

Signed-off-by: Mariusz Skamra <mariusz.skamra@codecoup.pl>
Signed-off-by: Vinayak Kariappa Chettimada <vich@nordicsemi.no>
2019-04-30 15:45:50 +02:00
Jiahao Li
84ae2f11ed Bluetooth: Mesh: Fixes existing friend lookup in Friend Request handling
Currently, when handling a Friend Request message with `prev_addr` set,
we look up existing friend entry using `prev_addr` as the address.
However, `prev_addr` is the address of the requesting node's previous
friend, NOT the address of the requesting node itself. Therefore, we
should always look up existing friend entry using `rx->ctx.addr` as the
address.

Signed-off-by: Jiahao Li <reg@ljh.me>
2019-01-29 07:23:22 -05:00
Johan Hedberg
5a0f7e44f1 Bluetooth: Mesh: Fix typo leading to incorrect settings storage
This was intended to be an equality comparison and not an assignment.

Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
2019-01-29 07:23:22 -05:00
Vinayak Kariappa Chettimada
da38403f9d Bluetooth: controller: Fix Conn Param Req procedure stall issue
Fix an issue wherein local or remote initiated Connection
Parameter Request procedure would stall without generation
of LE Connection Update Complete HCI event because a local
or remote initiated PHY Update procedure has overwritten the
currently active Link Layer Control Procedure type.

Signed-off-by: Vinayak Kariappa Chettimada <vinayak.kariappa@gmail.com>
2019-01-29 07:23:22 -05:00
Vinayak Kariappa Chettimada
7e7886782f Bluetooth: controller: Fix chan map update's diff trans collision
Fix channel map update procedure implementation's handling
of different transaction collision by not asserting but
disconnecting the connection due to invalid behavior by
peer implementation.

Signed-off-by: Vinayak Kariappa Chettimada <vich@nordicsemi.no>
2019-01-29 07:23:22 -05:00
Vinayak Kariappa Chettimada
07537107a8 Bluetooth: controller: Fix CPR procedure regression
This fixes regression introduced in commit a11868fea9.

Fixes the following conformance tests:
LL/CON/MAS/BV-32-C [Accepting Connection Parameter Request -
Preferred Periodicity]
LL/CON/MAS/BV-33-C [Accepting Connection Parameter Request -
Preferred Periodicity and preferred anchor points]

Signed-off-by: Vinayak Kariappa Chettimada <vich@nordicsemi.no>
2019-01-29 07:23:22 -05:00
Vinayak Kariappa Chettimada
210c27e370 Bluetooth: controller: Fix conn update assert in slave role
Explicitly track the connection update related ticker stop
and start to avoid asserting due to ticker update being done
at the same time for compensating the clock drift.

The compensation related ticker update failure in this case
can be safely ignored as new anchor point is used anyway
at the instant of the connection update.

Fixes #8796

Signed-off-by: Vinayak Kariappa Chettimada <vich@nordicsemi.no>
2019-01-29 07:23:22 -05:00
Luiz Augusto von Dentz
3637202c53 Bluetooth: GATT: Ensure GATT service is registered first
Accourding to Bluetooth specification the Service Changed
Characteristic shall not have its handle changed once it has been
bonded, so this moves the GATT service to be the very first service
registered that way it is guaranteed that it won't change even if
device is flashed with a different configuration which end up changing
the handles after it.

Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
2019-01-29 07:23:22 -05:00
Mariusz Skamra
a4d57234fc Bluetooth: Don't mask ECDH related events if CONFIG_BT_ECC disabled
It is related to b904ad387f.
This fixes checking ECDH related events in event mask.
If ECDH support is disabled in host, there is no need to check
if those are supported in the controller.

Signed-off-by: Mariusz Skamra <mariusz.skamra@codecoup.pl>
2019-01-29 07:23:22 -05:00
Luiz Augusto von Dentz
734ee4e57f Bluetooth: GATT: Fix not handling duplicated CCC storage
Some backends may actually contain the same key multiple times so the
code needs to check if there is already a ccc_cfg for an address before
attempting to use one that is unallocated.

Fixes #11409

Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
2019-01-29 07:23:22 -05:00
Luiz Augusto von Dentz
3769030f87 Bluetooth: GATT: Fix not resetting CCC storage
If there are no CCC to be stored the value should be set to NULL so it
is properly cleared otherwise calling settings_str_from_bytes will leave
str uninitialized which may cause a crash when attempting to load the
value.

Fixes #11564

Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
2019-01-29 07:23:22 -05:00
Mariusz Skamra
bb07b4d3fb Bluetooth: Add Kconfig option to disable HCI ECDH support
This adds Kconfig option to disable HCI ECDH support.
It will compile out ECDH related code, especially HCI event handlers.

Signed-off-by: Mariusz Skamra <mariusz.skamra@codecoup.pl>
2019-01-29 07:23:22 -05:00
Mariusz Skamra
82de097f20 Bluetooth: Add common Kconfig option to disable LE Data Length Update
This adds common option to disable support for LE Data Length Update
procedure in controller and host.
This will reduce flash usage by compiling out le_data_len_change
event handler that will never be called if controller has been
compiled with BT_CTLR_DATA_LENGTH option disabled.

Signed-off-by: Mariusz Skamra <mariusz.skamra@codecoup.pl>
2019-01-29 07:23:22 -05:00
Mariusz Skamra
00d62fbd68 Bluetooth: Add common Kconfig option to disable PHY Update
This adds common option to disable support for PHY Update
procedure in controller and host.
This will reduce flash usage by compiling out le_phy_update_complete
event handler that will never be called if controller has been
compiled with BT_CTLR_PHY option disabled.

Signed-off-by: Mariusz Skamra <mariusz.skamra@codecoup.pl>
2019-01-29 07:23:22 -05:00
Vinayak Kariappa Chettimada
e1f52c2800 Bluetooth: controller: Fix enable and disable of scan state
Updated controller implementation to disallow disabling
initiator state using scan disable. But allow disabling an
already disabled scan state. Also, disallow enabling scan
state while in initiator state.

Signed-off-by: Szymon Janc <szymon.janc@codecoup.pl>
Signed-off-by: Vinayak Kariappa Chettimada <vich@nordicsemi.no>
2019-01-29 07:23:22 -05:00
Vinayak Kariappa Chettimada
8f53d5ebe7 Bluetooth: controller: Do not feature exchange more than once
Updated the controller implementation to not feature
exchange if already done once either by local or remote peer
device in an active connection session.

Signed-off-by: Vinayak Kariappa Chettimada <vich@nordicsemi.no>
2019-01-29 07:23:22 -05:00
Szymon Janc
3517f9b2ef Bluetooth: host: Fix not starting slave conn param update timer
When issuing LE Set Data Length Command host should not assume that
LE Data Length Change Event will be generated. From Core Spec 5.0:
"If the command causes the maximum transmission packet size or maximum
packet transmission time to change, an LE Data Length Change Event
shall be generated."

Change-Id: I17723b58ed4f390aa465db3f69126ee229871123
Signed-off-by: Szymon Janc <szymon.janc@codecoup.pl>
2019-01-29 07:23:22 -05:00
Szymon Janc
c8ad2089ea Bluetooth: host: Don't send slave conn param request if not needed
If master or application decided to switch connection parameters to
ones that meet pending parameters don't bother sending request
after 5 seconds timeout.

Signed-off-by: Szymon Janc <szymon.janc@codecoup.pl>
2019-01-29 07:23:22 -05:00
Johan Hedberg
ebf9699f5b Bluetooth: Mesh: Increase scan window from 10ms to 30ms
Experiments have shown that the probability of missing advertising
packets is significantly lower with 30ms scan window compared to 10ms
scan window. This is especially the case with advertisers using a 20ms
advertising interval, which in turn is perhaps the most common one
since it's the smallest allowed by the Bluetooth 5.0 specification.

Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
2019-01-29 07:23:22 -05:00
Szymon Janc
623e8c2d17 Bluetooth: host: Don't restart scan if connection is pending
With multiple devices on auto-connect list it is possible that while
having pending connection to device A, device B disconnects. In that
case host should not try to start scan (currently controller doesn't
support concurrent scanning and initiating).

Signed-off-by: Szymon Janc <szymon.janc@codecoup.pl>
2019-01-29 07:23:22 -05:00
Vinayak Kariappa Chettimada
791b2bd83d Bluetooth: controller: Add min & max interval support in CPR
Add support for exchanging both minimum and maximum
connection interval values in Connection Parameter Request
Procedure implementation.

Signed-off-by: Vinayak Kariappa Chettimada <vich@nordicsemi.no>
2019-01-29 07:23:22 -05:00
Szymon Janc
335f231921 Bluetooth: host: Fallback to L2CAP for CPUP if rejected by master on LL
Fallback to L2CAP Connection Parameters Update Request if LL Connection
Update Request was rejected by remote device that has this marked as
supported in features. This can happen if procedure is supported only
by remote controller, but not enabled by host. This is connection
parameters update with iOS devices.

Signed-off-by: Szymon Janc <szymon.janc@codecoup.pl>
2019-01-29 07:23:22 -05:00
Mariusz Skamra
5b35b4568d Bluetooth: Do not compile GATT response handlers if Client is disabled
This will exclude GATT Client response handlers from compilation
if GATT Client support is disabled.

Signed-off-by: Mariusz Skamra <mariusz.skamra@codecoup.pl>
2019-01-29 07:23:22 -05:00
Vinayak Kariappa Chettimada
0a599e9283 Bluetooth: controller: Fix integer overflow in scheduling code
Fix an integer overflow in the scheduling implementation
that calculates whether resources required for next radio
event be retained.

Signed-off-by: Vinayak Kariappa Chettimada <vich@nordicsemi.no>
2019-01-29 07:23:22 -05:00
Szymon Janc
1f242b21fa Bluetooth: controller: Compile conn complete due to cancel conditionally
BT_HCI_ERR_UNKNOWN_CONN_ID can only be sent when master role is enabled.

Signed-off-by: Szymon Janc <szymon.janc@codecoup.pl>
2019-01-29 07:23:22 -05:00
Szymon Janc
78fdefecb6 Bluetooth: host: Compile master role conn complete conditionally
Connection complete event with error code can be received only for
central role and can be compiled conditionally.

Signed-off-by: Szymon Janc <szymon.janc@codecoup.pl>
2019-01-29 07:23:22 -05:00
Mariusz Skamra
5892a68041 Bluetooth: L2CAP: Extend available return codes from accept cb
This adds support for returning various return codes from
the channel accept callback.
This is needed for implementation of incoming connection
authorization for certification purposes.

Signed-off-by: Mariusz Skamra <mariusz.skamra@codecoup.pl>
2019-01-29 07:23:22 -05:00
Mariusz Skamra
31cdde8ca3 Bluetooth: L2CAP: Rename LE Connection Response Results
Rename connection response results to map those that are defined
for BR.
BR: BT_L2CAP_BR_*
LE: BT_L2CAP_LE_*

Signed-off-by: Mariusz Skamra <mariusz.skamra@codecoup.pl>
2019-01-29 07:23:22 -05:00
Szymon Janc
da62735763 Bluetooth: host: Avoid using out-of-scope pointer
Mkae sure that variable pointed by params is valid when passing it
as function argument.

Fixes #10587

Signed-off-by: Szymon Janc <szymon.janc@codecoup.pl>
2019-01-29 07:23:22 -05:00
Vinayak Kariappa Chettimada
f58ce51c2f Bluetooth: controller: Fix master role RSSI measurement
Fix broken master role RSSI measurement. Since the original
contribution clean up into Zephyr, the radio shorts that was
set for measuring the RSSI for master role has been broken,
as it was cleared by the radio switching code further in the
Tx ISR.

Signed-off-by: Vinayak Kariappa Chettimada <vich@nordicsemi.no>
2019-01-29 07:23:22 -05:00
Vinayak Kariappa Chettimada
308d2c0468 Bluetooth: controller: Fix connection failed to be established
Fix connection failed to be established regression
introduced by the commit 350c569aba ("Bluetooth:
controller: Avoid offseting to lldata").

As the Rx-ed PDU buffer is re-used to construct the
connection complete message towards HCI, the fields in the
Rx-ed PDU need to be backup for future use in the control
path. Here the channel selection bit is backup now.

Signed-off-by: Vinayak Kariappa Chettimada <vich@nordicsemi.no>
2019-01-29 07:23:22 -05:00
Vinayak Kariappa Chettimada
b79952c39d Bluetooth: controller: Fix conn param req procedure response
Fix Connection Parameter Request Procedure implementation
to respond with sent interval_min and interval_max so that
certain peer devices dont reject the response as Invalid LL
Parameters.

Signed-off-by: Vinayak Kariappa Chettimada <vich@nordicsemi.no>
2019-01-29 07:23:22 -05:00
Radoslaw Koppel
da5b22595f bluetooth: host: conn: Add const to addr in bt_le_set_auto_conn
This commit adds missed const modifier for addr pointer for
bt_le_set_auto_conn function

Signed-off-by: Radoslaw Koppel <radoslaw.koppel@nordicsemi.no>
2019-01-29 07:23:22 -05:00
Joakim Andersson
036bc5fbc0 bluetooth: config: Fix bluetooth config dependencies
Fix bluetooth config dependencies where the definitions depend on other
definitions.
BT_RX_PRIO is not always defined in a controller only build.
BT_CTLR_TX_BUFFER_SIZE does not depend on BT_CTLR, but BT_LL_SW.

Signed-off-by: Joakim Andersson <joakim.andersson@nordicsemi.no>
2019-01-29 07:23:22 -05:00
Vinayak Kariappa Chettimada
791dad637d Bluetooth: controller: Fix connection cancel deadlock
Calling bt_recv in the Bluetooth host Tx thread by the
controller implementation caused deadlock in combined host
controller builds when HCI LE Create Connection Cancel
generated the HCI LE Connection Complete or HCI LE Enhanced
Connection Complete events.

Controller's HCI implementation has been updated to place
the generated event into Rx FIFO to avoid the deadlock.

Relates to commit a59f544fb4 ("bluetooth: controller:
Handle non-priority events correctly")

Relates to #10314.

Signed-off-by: Vinayak Kariappa Chettimada <vich@nordicsemi.no>
2019-01-29 07:23:22 -05:00
Vinayak Kariappa Chettimada
9ffc9825b4 Bluetooth: controller: Avoid offseting to lldata
Avoid offseting to lldata when populating event structure
members.

Signed-off-by: Vinayak Kariappa Chettimada <vich@nordicsemi.no>
2019-01-29 07:23:22 -05:00
Szymon Janc
e934506635 Bluetooth: Fix autoconnect if cancelled pending connection
bt_conn_disconnect removes device from autoconnect list and thus
should not be called from le_conn_update when timeouting pending
connection. Also auto connect flag needs to be check on connection
failure to make sure scan is restarted.

Signed-off-by: Szymon Janc <szymon.janc@codecoup.pl>
2019-01-29 07:23:22 -05:00
Szymon Janc
a7814a6e1d Bluetooth: Fix incorrectly reporting connection as failure
Auto connect code reuses bt_conn object and connection code was assuming
object was cleared which resulted in invalid code being provided to
application. Fix that by explicitly setting error code to 0 on
successful connection.

Signed-off-by: Szymon Janc <szymon.janc@codecoup.pl>
2019-01-29 07:23:22 -05:00
Szymon Janc
eb1f5804b2 Bluetooth: Allow to configure LE Create Connection timeout
Depending on perhiperal advertising interval 3 seconds might not be
enough and would result in cancelling pending connection. Make this
Kconfig configurable and let application to decide.

Signed-off-by: Szymon Janc <szymon.janc@codecoup.pl>
2019-01-29 07:23:22 -05:00
Szymon Janc
ecda5c74a7 Bluetooth: Allow to configure background scan window and interval
Applications may require different scan windows and interval depending
on expected re-connection time or peer devices advertising parameters.
Default to GAP recommended slow values.

Signed-off-by: Szymon Janc <szymon.janc@codecoup.pl>
2019-01-29 07:23:22 -05:00
Vinayak Kariappa Chettimada
1310603c5f Bluetooth: controller: Fix Data Length Update implementation
The Data Length Update implementation reused the flags used
by Encryption Procedure which caused invalid Encryption
Procedure sequence under conditions where Data Length Update
Procedure collide with Encryption Setup initiated by the
peer central device.

Signed-off-by: Vinayak Kariappa Chettimada <vich@nordicsemi.no>
2019-01-29 07:23:22 -05:00
Kamil Piszczek
cdf6458122 Bluetooth: host: always set address via HCI before scanning
The address of the device is also set via HCI interface when passive
scanning is used. As a result, LL does not filter out directed
advertising packets that are targeted at this device.

Signed-off-by: Kamil Piszczek <Kamil.Piszczek@nordicsemi.no>
2019-01-29 07:23:22 -05:00
Szymon Janc
1c361f130c Bluetooth: Add option to configure peripheral connection parameters
This allows to configure desired parameters for peripheral. When set
PPCP characteristic is also added to GAP service. If disabled it is
up to application to controll connection parameters and stack will
only enforce 5 seconds delay before update.

Signed-off-by: Szymon Janc <szymon.janc@codecoup.pl>
2019-01-29 07:23:22 -05:00
Szymon Janc
6f1300d246 Bluetooth: Fix connection parameters update
This fixes a few issues with the handling of Connection Parameter
update in the Host:
 - starting conn param update timer as master
 - ignoring 5 seconds slave timer when calling bt_conn_le_param_update
 - starting conn param update timer on every PHY update

Signed-off-by: Szymon Janc <szymon.janc@codecoup.pl>
2019-01-29 07:23:22 -05:00
Szymon Janc
cb2476ccd3 Bluetooth: Controller: Add support for setting public address
This allows to provide public address for controller without using
VS HCI command from host. Useful for controller only builds or
combined builds that are not using VS HCI commands.

Signed-off-by: Szymon Janc <szymon.janc@codecoup.pl>
2019-01-29 07:23:22 -05:00
Szymon Janc
1b50ccab05 Bluetooth: Read static address from FICR on nRF5 if no VS enabled
When running combined build on nRF5 with disabled VS command it is
possible to simply read static random address from FICR in host.

Signed-off-by: Szymon Janc <szymon.janc@codecoup.pl>
2019-01-29 07:23:22 -05:00
Szymon Janc
732f1ac0b5 Bluetooth: Controller: Add CONFIG_BT_HCI_VS option
This allows to fully disable HCI VS commands support.

Signed-off-by: Szymon Janc <szymon.janc@codecoup.pl>
2019-01-29 07:23:22 -05:00
Szymon Janc
9e429e8e2d Bluetooth: Fix security level checking with LE SC and no-bonding
This was affecting SM/MAS/SCPK/BV-01-C qualification test case.

Signed-off-by: Szymon Janc <szymon.janc@codecoup.pl>
2019-01-29 07:23:22 -05:00
Mariusz Skamra
00cd24110a Bluetooth: Add a shell command to disable bondable mode
This adds a shell command for qualification purposes to enable/disable
Bonding flag in Authentication Requirements.

Signed-off-by: Mariusz Skamra <mariusz.skamra@codecoup.pl>
2019-01-29 07:23:22 -05:00
Mariusz Skamra
736e124671 Bluetooth: Add run-time option to disable SMP bondable mode
This adds a function that will disable Bonding flag in
Authentication Requirements flag in SMP Pairing Request/Response.
This is needed for qualification purposes.

Signed-off-by: Mariusz Skamra <mariusz.skamra@codecoup.pl>
2019-01-29 07:23:22 -05:00
Mariusz Skamra
7531653139 Bluetooth: Add Kconfig option to disable bondable mode
This adds Kconfig option to allow disable bondable mode in compile
time.

Signed-off-by: Mariusz Skamra <mariusz.skamra@codecoup.pl>
2019-01-29 07:23:22 -05:00
Luiz Augusto von Dentz
d50095351b Bluetooth: GATT: Make bt_gatt_discover perform discover all procedure
This makes bt_gatt_discover perform discover all proceduce if no UUID
is given in the parameters.

Fixes #9713

Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
2019-01-29 07:23:22 -05:00
Luiz Augusto von Dentz
346a9f0710 Bluetooth: GATT: Fix long write procedure
Long write procedure currently requires BT_GATT_PERM_PREPARE_WRITE to
be set otherwise the prepares would fail. This changes the behavior so
that BT_GATT_PERM_PREPARE_WRITE enables checking each prepare chunk
skipping it otherwise.

Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
2019-01-29 07:23:22 -05:00
Matias Karhumaa
e9c6e4d2f3 Bluetooth: hci_ecc: Fix byte order of dbg keys
Pass Bluetooth SMP debug keys to crypto API in correct byte order.

Fixes #9867

Signed-off-by: Matias Karhumaa <matias.karhumaa@gmail.com>
2019-01-29 07:23:22 -05:00
Johan Hedberg
85667eda09 Bluetooth: Remove bogus condition for setting IRK for an identity
Just like we set the address for an identity without depending on the
BT_DEV_READY flag, we should do the same for the IRK. Otherwise we
risk getting an all-zeroes IRK. Remove the condition and always set
the IRK value whenever CONFIG_BT_PRIVACY is enabled.

Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
2019-01-29 07:23:22 -05:00
Johan Hedberg
c32b5872b8 Bluetooth: Fix identity creation through vendor HCI
The code creating identities from the Read_Static_Addresses vendor
command was failing to create matching IRKs, resulting in an
all-zeroes IRK to be used. Fix this by using the existing id_create()
function which takes care of generaing an IRK when necessary.

Fixes #10003

Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
2019-01-29 07:23:22 -05:00
Johan Hedberg
cd4d2d67ee Bluetooth: Move bt_setup_id_addr() to avoid forward declaration
A subsequent patch will make bt_setup_id_addr() depend on id_create()
which was so far lower down in the hci_core.c c-file. Move
bt_setup_id_addr() further down to avoid a forward declaration.

Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
2019-01-29 07:23:22 -05:00
52 changed files with 1180 additions and 525 deletions

View File

@@ -209,7 +209,7 @@ struct bt_conn *bt_conn_create_le(const bt_addr_le_t *peer,
*
* @return Zero on success or error code otherwise.
*/
int bt_le_set_auto_conn(bt_addr_le_t *addr,
int bt_le_set_auto_conn(const bt_addr_le_t *addr,
const struct bt_le_conn_param *param);
/** @brief Initiate directed advertising to a remote device
@@ -386,6 +386,18 @@ struct bt_conn_cb {
*/
void bt_conn_cb_register(struct bt_conn_cb *cb);
/** Enable/disable bonding.
*
* Set/clear the Bonding flag in the Authentication Requirements of
* SMP Pairing Request/Response data.
* The initial value of this flag depends on BT_BONDABLE Kconfig setting.
* For the vast majority of applications calling this function shouldn't be
* needed.
*
* @param enable Value allowing/disallowing to be bondable.
*/
void bt_set_bondable(bool enable);
/** @def BT_PASSKEY_INVALID
*
* Special passkey value that can be used to disable a previously

View File

@@ -0,0 +1,39 @@
/** @file
* @brief Bluetooth subsystem controller APIs.
*/
/*
* Copyright (c) 2018 Codecoup
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef ZEPHYR_INCLUDE_BLUETOOTH_CONTROLLER_H_
#define ZEPHYR_INCLUDE_BLUETOOTH_CONTROLLER_H_
/**
* @brief Bluetooth Controller
* @defgroup bt_ctrl Bluetooth Controller
* @ingroup bluetooth
* @{
*/
#ifdef __cplusplus
extern "C" {
#endif
/** @brief Set public address for controller
*
* Should be called before bt_enable().
*
* @param addr Public address
*/
void bt_ctlr_set_public_addr(const u8_t *addr);
#ifdef __cplusplus
}
#endif
/**
* @}
*/
#endif /* ZEPHYR_INCLUDE_BLUETOOTH_CONTROLLER_H_ */

View File

@@ -240,6 +240,10 @@ struct bt_l2cap_server {
* @param chan Pointer to received the allocated channel
*
* @return 0 in case of success or negative value in case of error.
* Possible return values:
* -ENOMEM if no available space for new channel.
* -EACCES if application did not authorize the connection.
* -EPERM if encryption key size is too short.
*/
int (*accept)(struct bt_conn *conn, struct bt_l2cap_chan **chan);

View File

@@ -38,7 +38,7 @@ static struct k_thread tx_thread_data;
NET_BUF_POOL_DEFINE(cmd_tx_pool, CONFIG_BT_HCI_CMD_COUNT, CMD_BUF_SIZE,
BT_BUF_USER_DATA_MIN, NULL);
#if defined(CONFIG_BT_CTLR)
#if defined(CONFIG_BT_CTLR_TX_BUFFER_SIZE)
#define BT_L2CAP_MTU (CONFIG_BT_CTLR_TX_BUFFER_SIZE - BT_L2CAP_HDR_SIZE)
#else
#define BT_L2CAP_MTU 65 /* 64-byte public key + opcode */

View File

@@ -25,8 +25,8 @@ CONFIG_BT_BROADCASTER=y
CONFIG_BT_CTLR_LE_ENC=n
CONFIG_BT_CTLR_LE_PING=n
CONFIG_BT_CTLR_DATA_LENGTH=n
CONFIG_BT_CTLR_PHY=n
CONFIG_BT_DATA_LEN_UPDATE=n
CONFIG_BT_PHY_UPDATE=n
CONFIG_BT_CTLR_CHAN_SEL_2=n
CONFIG_BT_CTLR_MIN_USED_CHAN=n
CONFIG_BT_CTLR_ADV_EXT=n

View File

@@ -15,8 +15,8 @@ CONFIG_BT_BROADCASTER=y
CONFIG_BT_CTLR_DUP_FILTER_LEN=0
CONFIG_BT_CTLR_LE_ENC=n
CONFIG_BT_CTLR_LE_PING=n
CONFIG_BT_CTLR_DATA_LENGTH=n
CONFIG_BT_CTLR_PHY=n
CONFIG_BT_DATA_LEN_UPDATE=n
CONFIG_BT_PHY_UPDATE=n
CONFIG_BT_CTLR_CHAN_SEL_2=n
CONFIG_BT_CTLR_MIN_USED_CHAN=n
CONFIG_BT_CTLR_ADV_EXT=n

View File

@@ -24,8 +24,8 @@ CONFIG_BT_BROADCASTER=y
CONFIG_BT_CTLR_LE_ENC=n
CONFIG_BT_CTLR_LE_PING=n
CONFIG_BT_CTLR_DATA_LENGTH=n
CONFIG_BT_CTLR_PHY=n
CONFIG_BT_DATA_LEN_UPDATE=n
CONFIG_BT_PHY_UPDATE=n
CONFIG_BT_CTLR_CHAN_SEL_2=n
CONFIG_BT_CTLR_MIN_USED_CHAN=n
CONFIG_BT_CTLR_ADV_EXT=n

View File

@@ -11,8 +11,8 @@ CONFIG_BT_CTLR_DUP_FILTER_LEN=0
CONFIG_BT_CTLR_LE_ENC=n
CONFIG_BT_CTLR_LE_PING=n
CONFIG_BT_CTLR_DATA_LENGTH=n
CONFIG_BT_CTLR_PHY=n
CONFIG_BT_DATA_LEN_UPDATE=n
CONFIG_BT_PHY_UPDATE=n
CONFIG_BT_CTLR_CHAN_SEL_2=n
CONFIG_BT_CTLR_MIN_USED_CHAN=n
CONFIG_BT_CTLR_ADV_EXT=n

View File

@@ -19,8 +19,8 @@ CONFIG_BT_BROADCASTER=y
CONFIG_BT_CTLR_DUP_FILTER_LEN=0
CONFIG_BT_CTLR_LE_ENC=n
CONFIG_BT_CTLR_LE_PING=n
CONFIG_BT_CTLR_DATA_LENGTH=n
CONFIG_BT_CTLR_PHY=n
CONFIG_BT_DATA_LEN_UPDATE=n
CONFIG_BT_PHY_UPDATE=n
CONFIG_BT_CTLR_CHAN_SEL_2=n
CONFIG_BT_CTLR_MIN_USED_CHAN=n
CONFIG_BT_CTLR_ADV_EXT=n

View File

@@ -16,8 +16,8 @@ CONFIG_BT_BROADCASTER=y
CONFIG_BT_CTLR_DUP_FILTER_LEN=0
CONFIG_BT_CTLR_LE_ENC=n
CONFIG_BT_CTLR_LE_PING=n
CONFIG_BT_CTLR_DATA_LENGTH=n
CONFIG_BT_CTLR_PHY=n
CONFIG_BT_DATA_LEN_UPDATE=n
CONFIG_BT_PHY_UPDATE=n
CONFIG_BT_CTLR_CHAN_SEL_2=n
CONFIG_BT_CTLR_MIN_USED_CHAN=n
CONFIG_BT_CTLR_ADV_EXT=n

View File

@@ -85,6 +85,18 @@ config BT_OBSERVER
endmenu
config BT_PHY_UPDATE
bool "PHY Update"
default y
help
Enable support for Bluetooth 5.0 PHY Update Procedure.
config BT_DATA_LEN_UPDATE
bool "Data Length Update"
default y
help
Enable support for Bluetooth v4.2 LE Data Length Update procedure.
config BT_CONN
# Virtual/hidden option
bool

View File

@@ -8,12 +8,22 @@
if BT_HCI
config BT_HCI_VS
bool "Zephyr HCI Vendor-Specific Commands"
default y
help
Enable support for the Zephyr HCI Vendor-Specific Commmands in the
Host and/or Controller. This enables Set Version Information,
Supported Commands, Supported Features vendor commands.
config BT_HCI_VS_EXT
bool "Zephyr HCI Vendor-Specific Extensions"
depends on BT_HCI_VS
default y
help
Enable support for the Zephyr HCI Vendor-Specific Extensions in the
Host and/or Controller.
Host and/or Controller. This enables Write BD_ADDR, Read Build Info,
Read Static Addresses and Read Key Hierarchy Roots vendor commands.
config BT_HCI_VS_EXT_DETECT
bool "Use heuristics to guess HCI vendor extensions support in advance"

View File

@@ -11,12 +11,14 @@
#include <zephyr.h>
#if defined(CONFIG_BT_HCI_HOST)
/* The Bluetooth subsystem requires the Tx thread to execute at higher priority
* than the Rx thread as the Tx thread needs to process the acknowledgements
* before new Rx data is processed. This is a necessity to correctly detect
* transaction violations in ATT and SMP protocols.
*/
BUILD_ASSERT(CONFIG_BT_HCI_TX_PRIO < CONFIG_BT_RX_PRIO);
#endif
#if defined(CONFIG_BT_CTLR)
/* The Bluetooth Controller's priority receive thread priority shall be higher

View File

@@ -243,11 +243,10 @@ config BT_CTLR_EXT_SCAN_FP
in the Controller.
config BT_CTLR_DATA_LENGTH
bool "Data Length Update"
# Hidden option to enable support for Bluetooth v4.2 LE Data Length
bool
depends on BT_DATA_LEN_UPDATE
default y if SOC_SERIES_NRF52X
help
Enable support for Bluetooth v4.2 LE Data Length Update procedure in
the Controller.
config BT_CTLR_DATA_LENGTH_MAX
int "Maximum data length supported"
@@ -259,11 +258,11 @@ config BT_CTLR_DATA_LENGTH_MAX
Set the maximum data length of PDU supported in the Controller.
config BT_CTLR_PHY
bool "PHY Update"
# Hidden option to enable support for Bluetooth 5.0 PHY Update
# Procedure in the Controller.
bool
depends on BT_PHY_UPDATE
default y if SOC_SERIES_NRF52X
help
Enable support for Bluetooth 5.0 PHY Update Procedure in the
Controller.
endif # BT_CONN

View File

@@ -76,8 +76,8 @@ static u64_t event_mask_page_2 = DEFAULT_EVENT_MASK_PAGE_2;
static u64_t le_event_mask = DEFAULT_LE_EVENT_MASK;
#if defined(CONFIG_BT_CONN)
static void le_conn_complete(u8_t status, struct radio_le_conn_cmplt *radio_cc,
u16_t handle, struct net_buf *buf);
static void le_conn_complete(struct pdu_data *pdu_data, u16_t handle,
struct net_buf *buf);
#endif /* CONFIG_BT_CONN */
static void evt_create(struct net_buf *buf, u8_t evt, u8_t len)
@@ -1008,32 +1008,16 @@ static void le_create_connection(struct net_buf *buf, struct net_buf **evt)
*evt = cmd_status((!status) ? 0x00 : BT_HCI_ERR_CMD_DISALLOWED);
}
static void le_create_conn_cancel(struct net_buf *buf, struct net_buf **evt)
static void le_create_conn_cancel(struct net_buf *buf, struct net_buf **evt,
void **node_rx)
{
struct bt_hci_evt_cc_status *ccst;
struct net_buf *cc;
u8_t cmd_status;
u32_t status;
status = ll_connect_disable();
cmd_status = status ? BT_HCI_ERR_CMD_DISALLOWED : 0x00;
if (!cmd_status) {
*evt = bt_buf_get_rx(BT_BUF_EVT, K_FOREVER);
le_conn_complete(BT_HCI_ERR_UNKNOWN_CONN_ID, NULL, 0x0000,
*evt);
if ((*evt)->len) {
ccst = cmd_complete(&cc, sizeof(*ccst));
ccst->status = cmd_status;
bt_recv_prio(cc);
return;
} else {
net_buf_unref(*evt);
}
}
status = ll_connect_disable(node_rx);
ccst = cmd_complete(evt, sizeof(*ccst));
ccst->status = cmd_status;
ccst->status = (!status) ? 0x00 : BT_HCI_ERR_CMD_DISALLOWED;
}
static void le_set_host_chan_classif(struct net_buf *buf, struct net_buf **evt)
@@ -1132,18 +1116,21 @@ static void le_conn_update(struct net_buf *buf, struct net_buf **evt)
{
struct hci_cp_le_conn_update *cmd = (void *)buf->data;
u16_t supervision_timeout;
u16_t conn_interval_min;
u16_t conn_interval_max;
u16_t conn_latency;
u32_t status;
u16_t handle;
handle = sys_le16_to_cpu(cmd->handle);
conn_interval_min = sys_le16_to_cpu(cmd->conn_interval_min);
conn_interval_max = sys_le16_to_cpu(cmd->conn_interval_max);
conn_latency = sys_le16_to_cpu(cmd->conn_latency);
supervision_timeout = sys_le16_to_cpu(cmd->supervision_timeout);
status = ll_conn_update(handle, 0, 0, conn_interval_max,
conn_latency, supervision_timeout);
status = ll_conn_update(handle, 0, 0, conn_interval_min,
conn_interval_max, conn_latency,
supervision_timeout);
*evt = cmd_status(status);
}
@@ -1153,6 +1140,7 @@ static void le_conn_param_req_reply(struct net_buf *buf, struct net_buf **evt)
{
struct bt_hci_cp_le_conn_param_req_reply *cmd = (void *)buf->data;
struct bt_hci_rp_le_conn_param_req_reply *rp;
u16_t interval_min;
u16_t interval_max;
u16_t latency;
u16_t timeout;
@@ -1160,12 +1148,13 @@ static void le_conn_param_req_reply(struct net_buf *buf, struct net_buf **evt)
u16_t handle;
handle = sys_le16_to_cpu(cmd->handle);
interval_min = sys_le16_to_cpu(cmd->interval_min);
interval_max = sys_le16_to_cpu(cmd->interval_max);
latency = sys_le16_to_cpu(cmd->latency);
timeout = sys_le16_to_cpu(cmd->timeout);
status = ll_conn_update(handle, 2, 0, interval_max, latency,
timeout);
status = ll_conn_update(handle, 2, 0, interval_min, interval_max,
latency, timeout);
rp = cmd_complete(evt, sizeof(*rp));
rp->status = status;
@@ -1181,7 +1170,7 @@ static void le_conn_param_req_neg_reply(struct net_buf *buf,
u16_t handle;
handle = sys_le16_to_cpu(cmd->handle);
status = ll_conn_update(handle, 2, cmd->reason, 0, 0, 0);
status = ll_conn_update(handle, 2, cmd->reason, 0, 0, 0, 0);
rp = cmd_complete(evt, sizeof(*rp));
rp->status = status;
@@ -1513,7 +1502,7 @@ static void le_enh_tx_test(struct net_buf *buf, struct net_buf **evt)
#endif /* CONFIG_BT_CTLR_DTM_HCI */
static int controller_cmd_handle(u16_t ocf, struct net_buf *cmd,
struct net_buf **evt)
struct net_buf **evt, void **node_rx)
{
switch (ocf) {
case BT_OCF(BT_HCI_OP_LE_SET_EVENT_MASK):
@@ -1601,7 +1590,7 @@ static int controller_cmd_handle(u16_t ocf, struct net_buf *cmd,
break;
case BT_OCF(BT_HCI_OP_LE_CREATE_CONN_CANCEL):
le_create_conn_cancel(cmd, evt);
le_create_conn_cancel(cmd, evt, node_rx);
break;
case BT_OCF(BT_HCI_OP_LE_SET_HOST_CHAN_CLASSIF):
@@ -1741,6 +1730,7 @@ static int controller_cmd_handle(u16_t ocf, struct net_buf *cmd,
return 0;
}
#if defined(CONFIG_BT_HCI_VS)
static void vs_read_version_info(struct net_buf *buf, struct net_buf **evt)
{
struct bt_hci_rp_vs_read_version_info *rp;
@@ -1951,6 +1941,31 @@ static int vendor_cmd_handle(u16_t ocf, struct net_buf *cmd,
return 0;
}
#endif
#if !defined(CONFIG_BT_HCI_VS_EXT)
uint8_t bt_read_static_addr(bt_addr_le_t *addr)
{
#if defined(CONFIG_SOC_FAMILY_NRF)
if (((NRF_FICR->DEVICEADDR[0] != UINT32_MAX) ||
((NRF_FICR->DEVICEADDR[1] & UINT16_MAX) != UINT16_MAX)) &&
(NRF_FICR->DEVICEADDRTYPE & 0x01)) {
sys_put_le32(NRF_FICR->DEVICEADDR[0], &addr->a.val[0]);
sys_put_le16(NRF_FICR->DEVICEADDR[1], &addr->a.val[4]);
/* The FICR value is a just a random number, with no knowledge
* of the Bluetooth Specification requirements for random
* static addresses.
*/
BT_ADDR_SET_STATIC(&addr->a);
addr->type = BT_ADDR_LE_RANDOM;
return 1;
}
#endif /* CONFIG_SOC_FAMILY_NRF */
return 0;
}
#endif /* !CONFIG_BT_HCI_VS_EXT */
static void data_buf_overflow(struct net_buf **buf)
{
@@ -1967,7 +1982,7 @@ static void data_buf_overflow(struct net_buf **buf)
ep->link_type = BT_OVERFLOW_LINK_ACL;
}
struct net_buf *hci_cmd_handle(struct net_buf *cmd)
struct net_buf *hci_cmd_handle(struct net_buf *cmd, void **node_rx)
{
struct bt_hci_evt_cc_status *ccst;
struct bt_hci_cmd_hdr *chdr;
@@ -2007,11 +2022,13 @@ struct net_buf *hci_cmd_handle(struct net_buf *cmd)
err = status_cmd_handle(ocf, cmd, &evt);
break;
case BT_OGF_LE:
err = controller_cmd_handle(ocf, cmd, &evt);
err = controller_cmd_handle(ocf, cmd, &evt, node_rx);
break;
#if defined(CONFIG_BT_HCI_VS)
case BT_OGF_VS:
err = vendor_cmd_handle(ocf, cmd, &evt);
break;
#endif
default:
err = -EINVAL;
break;
@@ -2379,10 +2396,12 @@ static void le_scan_req_received(struct pdu_data *pdu_data, u8_t *b,
#endif /* CONFIG_BT_CTLR_SCAN_REQ_NOTIFY */
#if defined(CONFIG_BT_CONN)
static void le_conn_complete(u8_t status, struct radio_le_conn_cmplt *radio_cc,
u16_t handle, struct net_buf *buf)
static void le_conn_complete(struct pdu_data *pdu_data, u16_t handle,
struct net_buf *buf)
{
struct radio_le_conn_cmplt *radio_cc = (void *)pdu_data;
struct bt_hci_evt_le_conn_complete *lecc;
u8_t status = radio_cc->status;
#if defined(CONFIG_BT_CTLR_PRIVACY)
if (!status) {
@@ -2506,7 +2525,7 @@ static void le_conn_update_complete(struct pdu_data *pdu_data, u16_t handle,
return;
}
radio_cu = (void *)pdu_data->lldata;
radio_cu = (void *)pdu_data;
sep = meta_evt(buf, BT_HCI_EVT_LE_CONN_UPDATE_COMPLETE, sizeof(*sep));
@@ -2564,7 +2583,7 @@ static void le_chan_sel_algo(struct pdu_data *pdu_data, u16_t handle,
return;
}
radio_le_chan_sel_algo = (void *)pdu_data->lldata;
radio_le_chan_sel_algo = (void *)pdu_data;
sep = meta_evt(buf, BT_HCI_EVT_LE_CHAN_SEL_ALGO, sizeof(*sep));
@@ -2580,7 +2599,7 @@ static void le_phy_upd_complete(struct pdu_data *pdu_data, u16_t handle,
struct bt_hci_evt_le_phy_update_complete *sep;
struct radio_le_phy_upd_cmplt *radio_le_phy_upd_cmplt;
radio_le_phy_upd_cmplt = (void *)pdu_data->lldata;
radio_le_phy_upd_cmplt = (void *)pdu_data;
if (!(event_mask & BT_EVT_MASK_LE_META_EVENT) ||
!(le_event_mask & BT_EVT_MASK_LE_PHY_UPDATE_COMPLETE)) {
@@ -2632,12 +2651,7 @@ static void encode_control(struct radio_pdu_node_rx *node_rx,
#if defined(CONFIG_BT_CONN)
case NODE_RX_TYPE_CONNECTION:
{
struct radio_le_conn_cmplt *cc;
cc = (void *)pdu_data->lldata;
le_conn_complete(cc->status, cc, handle, buf);
}
le_conn_complete(pdu_data, handle, buf);
break;
case NODE_RX_TYPE_TERMINATE:
@@ -2809,7 +2823,7 @@ static void le_conn_param_req(struct pdu_data *pdu_data, u16_t handle,
if (!(event_mask & BT_EVT_MASK_LE_META_EVENT) ||
!(le_event_mask & BT_EVT_MASK_LE_CONN_PARAM_REQ)) {
/* event masked, reject the conn param req */
ll_conn_update(handle, 2, BT_HCI_ERR_UNSUPP_REMOTE_FEATURE,
ll_conn_update(handle, 2, BT_HCI_ERR_UNSUPP_REMOTE_FEATURE, 0,
0, 0, 0);
return;

View File

@@ -348,17 +348,17 @@ static void recv_thread(void *p1, void *p2, void *p3)
static int cmd_handle(struct net_buf *buf)
{
struct bt_hci_evt_hdr *hdr;
void *node_rx = NULL;
struct net_buf *evt;
evt = hci_cmd_handle(buf);
evt = hci_cmd_handle(buf, &node_rx);
if (evt) {
hdr = (void *)evt->data;
BT_DBG("Replying with event of %u bytes", evt->len);
if (unlikely(!bt_hci_evt_is_prio(hdr->evt))) {
bt_recv(evt);
} else {
bt_recv_prio(evt);
bt_recv_prio(evt);
if (node_rx) {
BT_DBG("RX node enqueue");
k_fifo_put(&recv_fifo, node_rx);
}
}

View File

@@ -32,7 +32,7 @@ extern atomic_t hci_state_mask;
#endif /* CONFIG_SOC_FAMILY_NRF */
void hci_init(struct k_poll_signal *signal_host_buf);
struct net_buf *hci_cmd_handle(struct net_buf *cmd);
struct net_buf *hci_cmd_handle(struct net_buf *cmd, void **node_rx);
void hci_evt_encode(struct radio_pdu_node_rx *node_rx, struct net_buf *buf);
s8_t hci_get_class(struct radio_pdu_node_rx *node_rx);
#if defined(CONFIG_BT_CONN)

View File

@@ -54,10 +54,9 @@ u32_t ll_create_connection(u16_t scan_interval, u16_t scan_window,
u8_t *p_peer_addr, u8_t own_addr_type,
u16_t interval, u16_t latency,
u16_t timeout);
u32_t ll_connect_disable(void);
u32_t ll_conn_update(u16_t handle, u8_t cmd, u8_t status,
u16_t interval, u16_t latency,
u16_t timeout);
u32_t ll_connect_disable(void **node_rx);
u32_t ll_conn_update(u16_t handle, u8_t cmd, u8_t status, u16_t interval_min,
u16_t interval_max, u16_t latency, u16_t timeout);
u32_t ll_chm_update(u8_t *chm);
u32_t ll_chm_get(u16_t handle, u8_t *chm);
u32_t ll_enc_req_send(u16_t handle, u8_t *rand, u8_t *ediv,

View File

@@ -167,6 +167,7 @@ static struct {
u8_t volatile ticker_id_prepare;
u8_t volatile ticker_id_event;
u8_t volatile ticker_id_stop;
u8_t volatile ticker_id_upd;
enum role volatile role;
enum state state;
@@ -250,10 +251,12 @@ static u16_t const gc_lookup_ppm[] = { 500, 250, 150, 100, 75, 50, 30, 20 };
static void common_init(void);
static void ticker_success_assert(u32_t status, void *params);
static void ticker_update_adv_assert(u32_t status, void *params);
static void ticker_stop_adv_assert(u32_t status, void *params);
static void ticker_stop_scan_assert(u32_t status, void *params);
static void ticker_update_adv_assert(u32_t status, void *params);
static void ticker_update_slave_assert(u32_t status, void *params);
static void ticker_stop_slave_assert(u32_t status, void *params);
static void ticker_start_slave_assert(u32_t status, void *params);
static void event_inactive(u32_t ticks_at_expire, u32_t remainder,
u16_t lazy, void *context);
@@ -300,8 +303,8 @@ static u8_t conn_update(struct connection *conn, struct pdu_data *pdu_data_rx);
static u32_t conn_update_req(struct connection *conn);
#endif /* CONFIG_BT_CTLR_XTAL_ADVANCED && CONFIG_BT_CTLR_SCHED_ADVANCED */
static u32_t chan_map_update(struct connection *conn,
struct pdu_data *pdu_data_rx);
static u8_t chan_map_update(struct connection *conn,
struct pdu_data *pdu_data_rx);
#if defined(CONFIG_BT_CTLR_PHY)
static inline u8_t phy_upd_ind_recv(struct radio_pdu_node_rx *node_rx,
@@ -715,15 +718,6 @@ static inline void isr_radio_state_tx(void)
break;
case ROLE_MASTER:
#if defined(CONFIG_BT_CTLR_CONN_RSSI)
if (_radio.packet_counter == 0) {
radio_rssi_measure();
}
#endif /* CONFIG_BT_CTLR_CONN_RSSI */
/* fall thru */
case ROLE_SLAVE:
#if defined(CONFIG_BT_CTLR_PHY)
@@ -753,6 +747,13 @@ static inline void isr_radio_state_tx(void)
radio_tmr_hcto_configure(hcto);
#if defined(CONFIG_BT_CTLR_CONN_RSSI)
if ((_radio.role == ROLE_MASTER) &&
(_radio.packet_counter == 0)) {
radio_rssi_measure();
}
#endif /* CONFIG_BT_CTLR_CONN_RSSI */
#if defined(CONFIG_BT_CTLR_GPIO_LNA_PIN)
#if defined(CONFIG_BT_CTLR_PHY)
radio_gpio_pa_lna_enable(radio_tmr_tifs_base_get() +
@@ -961,7 +962,6 @@ static inline u32_t isr_rx_adv(u8_t devmatch_ok, u8_t devmatch_id,
((_radio.fc_ena == 0) || (_radio.fc_req == _radio.fc_ack)) &&
(_radio.advertiser.conn)) {
struct radio_le_conn_cmplt *radio_le_conn_cmplt;
struct pdu_data *pdu_data;
struct connection *conn;
u32_t ticks_slot_offset;
u32_t conn_interval_us;
@@ -1033,8 +1033,7 @@ static inline u32_t isr_rx_adv(u8_t devmatch_ok, u8_t devmatch_id,
node_rx->hdr.type = NODE_RX_TYPE_CONNECTION;
/* prepare connection complete structure */
pdu_data = (void *)node_rx->pdu_data;
radio_le_conn_cmplt = (void *)pdu_data->lldata;
radio_le_conn_cmplt = (void *)node_rx->pdu_data;
radio_le_conn_cmplt->status = 0x00;
radio_le_conn_cmplt->role = 0x01;
#if defined(CONFIG_BT_CTLR_PRIVACY)
@@ -1090,8 +1089,7 @@ static inline u32_t isr_rx_adv(u8_t devmatch_ok, u8_t devmatch_id,
node_rx->hdr.handle = conn->handle;
node_rx->hdr.type = NODE_RX_TYPE_CHAN_SEL_ALGO;
pdu_data = (void *)node_rx->pdu_data;
le_chan_sel_algo = (void *)pdu_data->lldata;
le_chan_sel_algo = (void *)node_rx->pdu_data;
if (pdu_adv->chan_sel) {
u16_t aa_ls =
@@ -1353,7 +1351,7 @@ static inline u32_t isr_rx_scan(u8_t devmatch_ok, u8_t devmatch_id,
struct radio_le_conn_cmplt *radio_le_conn_cmplt;
struct radio_pdu_node_rx *node_rx;
struct pdu_adv *pdu_adv_tx;
struct pdu_data *pdu_data;
u8_t pdu_adv_rx_chan_sel;
struct connection *conn;
u32_t ticks_slot_offset;
u32_t conn_interval_us;
@@ -1386,6 +1384,11 @@ static inline u32_t isr_rx_scan(u8_t devmatch_ok, u8_t devmatch_id,
if (IS_ENABLED(CONFIG_BT_CTLR_CHAN_SEL_2)) {
pdu_adv_tx->chan_sel = 1;
/* backup, as Rx-ed buffer is used to enqueue
* connection message.
*/
pdu_adv_rx_chan_sel = pdu_adv_rx->chan_sel;
} else {
pdu_adv_tx->chan_sel = 0;
}
@@ -1498,8 +1501,7 @@ static inline u32_t isr_rx_scan(u8_t devmatch_ok, u8_t devmatch_id,
node_rx->hdr.type = NODE_RX_TYPE_CONNECTION;
/* prepare connection complete structure */
pdu_data = (void *)node_rx->pdu_data;
radio_le_conn_cmplt = (void *)pdu_data->lldata;
radio_le_conn_cmplt = (void *)node_rx->pdu_data;
radio_le_conn_cmplt->status = 0x00;
radio_le_conn_cmplt->role = 0x00;
#if defined(CONFIG_BT_CTLR_PRIVACY)
@@ -1555,10 +1557,9 @@ static inline u32_t isr_rx_scan(u8_t devmatch_ok, u8_t devmatch_id,
node_rx->hdr.handle = conn->handle;
node_rx->hdr.type = NODE_RX_TYPE_CHAN_SEL_ALGO;
pdu_data = (void *)node_rx->pdu_data;
le_chan_sel_algo = (void *)pdu_data->lldata;
le_chan_sel_algo = (void *)node_rx->pdu_data;
if (pdu_adv_rx->chan_sel) {
if (pdu_adv_rx_chan_sel) {
u16_t aa_ls =
((u16_t)conn->access_addr[1] << 8) |
conn->access_addr[0];
@@ -1839,7 +1840,7 @@ static inline u8_t isr_rx_conn_pkt_ack(struct pdu_data *pdu_data_tx,
(_radio.conn_curr->llcp_length.state ==
LLCP_LENGTH_STATE_ACK_WAIT)){
/* pause data packet tx */
_radio.conn_curr->pause_tx = 1;
_radio.conn_curr->llcp_length.pause_tx = 1;
/* wait for response */
_radio.conn_curr->llcp_length.state =
@@ -1944,7 +1945,8 @@ isr_rx_conn_pkt_ctrl_rej_conn_upd(struct radio_pdu_node_rx *node_rx,
conn->llcp.conn_upd.win_size = 1;
conn->llcp.conn_upd.win_offset_us = 0;
conn->llcp.conn_upd.interval = conn->llcp_conn_param.interval;
conn->llcp.conn_upd.interval =
conn->llcp_conn_param.interval_max;
conn->llcp.conn_upd.latency = conn->llcp_conn_param.latency;
conn->llcp.conn_upd.timeout = conn->llcp_conn_param.timeout;
/* conn->llcp.conn_upd.instant = 0; */
@@ -1955,29 +1957,26 @@ isr_rx_conn_pkt_ctrl_rej_conn_upd(struct radio_pdu_node_rx *node_rx,
return;
}
/* Same Procedure or Different Procedure Collision */
/* If not same procedure, stop procedure timeout, else
* continue timer until phy upd ind is received.
*/
/* FIXME: handle unsupported LL parameters error */
else if (rej_ext_ind->error_code != BT_HCI_ERR_LL_PROC_COLLISION) {
/* update to next ticks offsets */
if (conn->role) {
conn->slave.ticks_to_offset =
conn->llcp_conn_param.ticks_to_offset_next;
}
}
if (conn->llcp_conn_param.state == LLCP_CPR_STATE_RSP_WAIT) {
LL_ASSERT(_radio.conn_upd == conn);
/* reset mutex */
_radio.conn_upd = NULL;
/* Procedure complete */
conn->llcp_conn_param.ack =
conn->llcp_conn_param.req;
conn->llcp_conn_param.ack = conn->llcp_conn_param.req;
/* Stop procedure timeout */
conn->procedure_expire = 0;
/* update to next ticks offsets */
if (conn->role) {
conn->slave.ticks_to_offset =
conn->llcp_conn_param.ticks_to_offset_next;
}
}
/* skip event generation if not cmd initiated */
@@ -1989,8 +1988,7 @@ isr_rx_conn_pkt_ctrl_rej_conn_upd(struct radio_pdu_node_rx *node_rx,
node_rx->hdr.type = NODE_RX_TYPE_CONN_UPDATE;
/* prepare connection update complete structure */
pdu_data_rx = (void *)node_rx->pdu_data;
cp = (void *)pdu_data_rx->lldata;
cp = (void *)pdu_data_rx;
cp->status = rej_ext_ind->error_code;
cp->interval = conn->conn_interval;
cp->latency = conn->latency;
@@ -2017,11 +2015,9 @@ isr_rx_conn_pkt_ctrl_rej_dle(struct radio_pdu_node_rx *node_rx,
/* Procedure complete */
conn->llcp_length.ack = conn->llcp_length.req;
conn->llcp_length.pause_tx = 0;
conn->procedure_expire = 0;
/* Resume data packet tx */
conn->pause_tx = 0;
/* prepare length rsp structure */
pdu_data_rx->len = offsetof(struct pdu_data_llctrl,
length_rsp) +
@@ -2084,7 +2080,7 @@ isr_rx_conn_pkt_ctrl_rej_phy_upd(struct radio_pdu_node_rx *node_rx,
/* generate phy update complete event with error code */
node_rx->hdr.type = NODE_RX_TYPE_PHY_UPDATE;
p = (void *)pdu_data_rx->lldata;
p = (void *)pdu_data_rx;
p->status = rej_ext_ind->error_code;
p->tx = _radio.conn_curr->phy_tx;
p->rx = _radio.conn_curr->phy_rx;
@@ -2295,11 +2291,9 @@ static inline u8_t isr_rx_conn_pkt_ctrl_dle(struct pdu_data *pdu_data_rx,
/* Procedure complete */
_radio.conn_curr->llcp_length.ack =
_radio.conn_curr->llcp_length.req;
_radio.conn_curr->llcp_length.pause_tx = 0;
_radio.conn_curr->procedure_expire = 0;
/* resume data packet tx */
_radio.conn_curr->pause_tx = 0;
/* No change in effective octets or time */
if (eff_tx_octets == _radio.conn_curr->max_tx_octets &&
#if defined(CONFIG_BT_CTLR_PHY)
@@ -2453,17 +2447,21 @@ isr_rx_conn_pkt_ctrl(struct radio_pdu_node_rx *node_rx, u8_t *rx_enqueue)
break;
case PDU_DATA_LLCTRL_TYPE_CHAN_MAP_IND:
{
u8_t err;
if (!_radio.conn_curr->role ||
!pdu_len_cmp(PDU_DATA_LLCTRL_TYPE_CHAN_MAP_IND,
pdu_data_rx->len)) {
goto isr_rx_conn_unknown_rsp_send;
}
if (chan_map_update(_radio.conn_curr, pdu_data_rx)) {
_radio.conn_curr->llcp_terminate.reason_peer =
BT_HCI_ERR_INSTANT_PASSED;
err = chan_map_update(_radio.conn_curr, pdu_data_rx);
if (err) {
_radio.conn_curr->llcp_terminate.reason_peer = err;
}
break;
}
break;
case PDU_DATA_LLCTRL_TYPE_TERMINATE_IND:
if (!pdu_len_cmp(PDU_DATA_LLCTRL_TYPE_TERMINATE_IND,
@@ -2769,7 +2767,10 @@ isr_rx_conn_pkt_ctrl(struct radio_pdu_node_rx *node_rx, u8_t *rx_enqueue)
/* save parameters to be used to select offset
*/
conn->llcp_conn_param.interval = cpr->interval_min;
conn->llcp_conn_param.interval_min =
cpr->interval_min;
conn->llcp_conn_param.interval_max =
cpr->interval_max;
conn->llcp_conn_param.latency = cpr->latency;
conn->llcp_conn_param.timeout = cpr->timeout;
conn->llcp_conn_param.preferred_periodicity =
@@ -2786,7 +2787,7 @@ isr_rx_conn_pkt_ctrl(struct radio_pdu_node_rx *node_rx, u8_t *rx_enqueue)
/* enqueue the conn param req, if parameters
* changed, else respond.
*/
if ((conn->llcp_conn_param.interval !=
if ((conn->llcp_conn_param.interval_max !=
conn->conn_interval) ||
(conn->llcp_conn_param.latency !=
conn->latency) ||
@@ -2849,7 +2850,8 @@ isr_rx_conn_pkt_ctrl(struct radio_pdu_node_rx *node_rx, u8_t *rx_enqueue)
/* resp to be generated by app, for now save
* parameters
*/
conn->llcp_conn_param.interval = cpr->interval_min;
conn->llcp_conn_param.interval_min = cpr->interval_min;
conn->llcp_conn_param.interval_max = cpr->interval_max;
conn->llcp_conn_param.latency = cpr->latency;
conn->llcp_conn_param.timeout = cpr->timeout;
conn->llcp_conn_param.preferred_periodicity =
@@ -2866,7 +2868,7 @@ isr_rx_conn_pkt_ctrl(struct radio_pdu_node_rx *node_rx, u8_t *rx_enqueue)
/* enqueue the conn param req, if parameters changed,
* else respond
*/
if ((conn->llcp_conn_param.interval !=
if ((conn->llcp_conn_param.interval_max !=
conn->conn_interval) ||
(conn->llcp_conn_param.latency != conn->latency) ||
(RADIO_CONN_EVENTS(conn->llcp_conn_param.timeout *
@@ -2932,7 +2934,8 @@ isr_rx_conn_pkt_ctrl(struct radio_pdu_node_rx *node_rx, u8_t *rx_enqueue)
/* save parameters to be used to select offset
*/
conn->llcp_conn_param.interval = cpr->interval_min;
conn->llcp_conn_param.interval_min = cpr->interval_min;
conn->llcp_conn_param.interval_max = cpr->interval_max;
conn->llcp_conn_param.latency = cpr->latency;
conn->llcp_conn_param.timeout = cpr->timeout;
conn->llcp_conn_param.preferred_periodicity =
@@ -3008,7 +3011,7 @@ isr_rx_conn_pkt_ctrl(struct radio_pdu_node_rx *node_rx, u8_t *rx_enqueue)
conn->llcp.conn_upd.win_size = 1;
conn->llcp.conn_upd.win_offset_us = 0;
conn->llcp.conn_upd.interval =
conn->llcp_conn_param.interval;
conn->llcp_conn_param.interval_max;
conn->llcp.conn_upd.latency =
conn->llcp_conn_param.latency;
conn->llcp.conn_upd.timeout =
@@ -3040,8 +3043,7 @@ isr_rx_conn_pkt_ctrl(struct radio_pdu_node_rx *node_rx, u8_t *rx_enqueue)
node_rx->hdr.type = NODE_RX_TYPE_CONN_UPDATE;
/* prepare connection update complete structure */
pdu_data_rx = (void *)node_rx->pdu_data;
cp = (void *)pdu_data_rx->lldata;
cp = (void *)pdu_data_rx;
cp->status = BT_HCI_ERR_UNSUPP_REMOTE_FEATURE;
cp->interval = conn->conn_interval;
cp->latency = conn->latency;
@@ -3057,9 +3059,7 @@ isr_rx_conn_pkt_ctrl(struct radio_pdu_node_rx *node_rx, u8_t *rx_enqueue)
/* Procedure complete */
_radio.conn_curr->llcp_length.ack =
_radio.conn_curr->llcp_length.req;
/* resume data packet tx */
_radio.conn_curr->pause_tx = 0;
_radio.conn_curr->llcp_length.pause_tx = 0;
/* propagate the data length procedure to
* host
@@ -3085,7 +3085,7 @@ isr_rx_conn_pkt_ctrl(struct radio_pdu_node_rx *node_rx, u8_t *rx_enqueue)
/* generate phy update complete event */
node_rx->hdr.type = NODE_RX_TYPE_PHY_UPDATE;
p = (void *)pdu_data_rx->lldata;
p = (void *)pdu_data_rx;
p->status = 0;
p->tx = _radio.conn_curr->phy_tx;
p->rx = _radio.conn_curr->phy_rx;
@@ -4463,6 +4463,14 @@ static void ticker_success_assert(u32_t status, void *params)
LL_ASSERT(status == TICKER_STATUS_SUCCESS);
}
static void ticker_update_adv_assert(u32_t status, void *params)
{
ARG_UNUSED(params);
LL_ASSERT((status == TICKER_STATUS_SUCCESS) ||
(_radio.ticker_id_stop == RADIO_TICKER_ID_ADV));
}
static void ticker_stop_adv_assert(u32_t status, void *params)
{
ARG_UNUSED(params);
@@ -4513,20 +4521,27 @@ static void ticker_stop_scan_assert(u32_t status, void *params)
}
}
static void ticker_update_adv_assert(u32_t status, void *params)
{
ARG_UNUSED(params);
LL_ASSERT((status == TICKER_STATUS_SUCCESS) ||
(_radio.ticker_id_stop == RADIO_TICKER_ID_ADV));
}
static void ticker_update_slave_assert(u32_t status, void *params)
{
u8_t ticker_id = (u32_t)params & 0xFF;
LL_ASSERT((status == TICKER_STATUS_SUCCESS) ||
(_radio.ticker_id_stop == ticker_id));
(_radio.ticker_id_stop == ticker_id) ||
(_radio.ticker_id_upd == ticker_id));
}
static void ticker_stop_slave_assert(u32_t status, void *params)
{
LL_ASSERT(status == TICKER_STATUS_SUCCESS);
_radio.ticker_id_upd = (u8_t)((u32_t)params & 0xFF);
}
static void ticker_start_slave_assert(u32_t status, void *params)
{
LL_ASSERT(status == TICKER_STATUS_SUCCESS);
_radio.ticker_id_upd = 0;
}
static void mayfly_radio_active(void *params)
@@ -4886,9 +4901,15 @@ static void mayfly_xtal_stop_calc(void *params)
/* Compensate for next ticker in reduced prepare */
if (hdr_next->ticks_xtal_to_start & XON_BITMASK) {
ticks_to_expire -=
(hdr_next->ticks_xtal_to_start &
~XON_BITMASK) - ticks_prepare_to_start_next;
u32_t ticks_reduced = (hdr_next->ticks_xtal_to_start &
~XON_BITMASK) -
ticks_prepare_to_start_next;
if (ticks_to_expire > ticks_reduced) {
ticks_to_expire -= ticks_reduced;
} else {
ticks_to_expire = 0;
}
}
/* If beyond the xtal threshold reset to normal the next prepare,
@@ -5356,7 +5377,8 @@ static void mayfly_sched_free_win_offset_calc(void *params)
}
sched_free_win_offset_calc(conn, 0, ticks_to_offset_next,
conn->llcp_conn_param.interval, &offset_max,
conn->llcp_conn_param.interval_max,
&offset_max,
(u8_t *)conn->llcp_conn_param.pdu_win_offset0);
}
@@ -5376,7 +5398,7 @@ static void mayfly_sched_win_offset_select(void *params)
1250);
sched_free_win_offset_calc(conn, 1, &ticks_to_offset,
conn->llcp_conn_param.interval,
conn->llcp_conn_param.interval_max,
&offset_m_max, (u8_t *)&win_offset_m[0]);
while (offset_index_s < OFFSET_S_MAX) {
@@ -6209,7 +6231,6 @@ static void mayfly_adv_stop(void *param)
{
struct radio_le_conn_cmplt *radio_le_conn_cmplt;
struct radio_pdu_node_rx *node_rx;
struct pdu_data *pdu_data_rx;
/* Prepare the rx packet structure */
node_rx = packet_rx_reserve_get(1);
@@ -6220,8 +6241,7 @@ static void mayfly_adv_stop(void *param)
node_rx->hdr.type = NODE_RX_TYPE_CONNECTION;
/* prepare connection complete structure */
pdu_data_rx = (void *)node_rx->pdu_data;
radio_le_conn_cmplt = (void *)pdu_data_rx->lldata;
radio_le_conn_cmplt = (void *)node_rx->pdu_data;
memset(radio_le_conn_cmplt, 0x00, sizeof(struct radio_le_conn_cmplt));
radio_le_conn_cmplt->status = BT_HCI_ERR_ADV_TIMEOUT;
@@ -6718,18 +6738,18 @@ static inline u32_t event_conn_upd_prep(struct connection *conn,
ctrl_tx_enqueue(conn, node_tx);
} else if (instant_latency <= 0x7FFF) {
struct radio_pdu_node_rx *node_rx;
struct pdu_data *pdu_data_rx;
struct radio_le_conn_update_cmplt *radio_le_conn_update_cmplt;
u32_t ticker_status;
u32_t conn_interval_us;
u32_t periodic_us;
u32_t ticks_win_offset;
u32_t ticks_slot_offset;
struct radio_pdu_node_rx *node_rx;
u32_t mayfly_was_enabled;
u16_t conn_interval_old;
u16_t conn_interval_new;
u32_t ticks_slot_offset;
u32_t ticks_win_offset;
u32_t conn_interval_us;
u32_t ticker_status;
u32_t periodic_us;
u8_t ticker_id;
u16_t latency;
u32_t mayfly_was_enabled;
/* procedure request acked */
conn->llcp_ack = conn->llcp_req;
@@ -6769,11 +6789,8 @@ static inline u32_t event_conn_upd_prep(struct connection *conn,
node_rx->hdr.type = NODE_RX_TYPE_CONN_UPDATE;
/* prepare connection update complete structure */
pdu_data_rx = (void *)node_rx->pdu_data;
radio_le_conn_update_cmplt = (void *)
pdu_data_rx->lldata;
radio_le_conn_update_cmplt->status =
0x00;
radio_le_conn_update_cmplt = (void *) node_rx->pdu_data;
radio_le_conn_update_cmplt->status = 0x00;
radio_le_conn_update_cmplt->interval =
conn->llcp.conn_upd.interval;
radio_le_conn_update_cmplt->latency =
@@ -6896,19 +6913,17 @@ static inline u32_t event_conn_upd_prep(struct connection *conn,
RADIO_TICKER_USER_ID_JOB, 0);
/* start slave/master with new timings */
ticker_id = RADIO_TICKER_ID_FIRST_CONNECTION + conn->handle;
ticker_status =
ticker_stop(RADIO_TICKER_INSTANCE_ID_RADIO,
RADIO_TICKER_USER_ID_WORKER,
RADIO_TICKER_ID_FIRST_CONNECTION +
conn->handle, ticker_success_assert,
(void *)__LINE__);
RADIO_TICKER_USER_ID_WORKER, ticker_id,
ticker_stop_slave_assert,
(void *)(u32_t)ticker_id);
LL_ASSERT((ticker_status == TICKER_STATUS_SUCCESS) ||
(ticker_status == TICKER_STATUS_BUSY));
ticker_status =
ticker_start(RADIO_TICKER_INSTANCE_ID_RADIO,
RADIO_TICKER_USER_ID_WORKER,
RADIO_TICKER_ID_FIRST_CONNECTION +
conn->handle,
RADIO_TICKER_USER_ID_WORKER, ticker_id,
ticks_at_expire, ticks_win_offset,
HAL_TICKER_US_TO_TICKS(periodic_us),
HAL_TICKER_REMAINDER(periodic_us),
@@ -6916,8 +6931,8 @@ static inline u32_t event_conn_upd_prep(struct connection *conn,
(ticks_slot_offset + conn->hdr.ticks_slot),
conn->role ?
event_slave_prepare : event_master_prepare,
conn, ticker_success_assert,
(void *)__LINE__);
conn, ticker_start_slave_assert,
(void *)(u32_t)ticker_id);
LL_ASSERT((ticker_status == TICKER_STATUS_SUCCESS) ||
(ticker_status == TICKER_STATUS_BUSY));
@@ -7157,6 +7172,42 @@ static inline void event_fex_prep(struct connection *conn)
{
struct radio_pdu_node_tx *node_tx;
if (conn->common.fex_valid) {
struct radio_pdu_node_rx *node_rx;
struct pdu_data *pdu_ctrl_rx;
/* procedure request acked */
conn->llcp_ack = conn->llcp_req;
/* Prepare the rx packet structure */
node_rx = packet_rx_reserve_get(2);
LL_ASSERT(node_rx);
node_rx->hdr.handle = conn->handle;
node_rx->hdr.type = NODE_RX_TYPE_DC_PDU;
/* prepare feature rsp structure */
pdu_ctrl_rx = (void *)node_rx->pdu_data;
pdu_ctrl_rx->ll_id = PDU_DATA_LLID_CTRL;
pdu_ctrl_rx->len = offsetof(struct pdu_data_llctrl,
feature_rsp) +
sizeof(struct pdu_data_llctrl_feature_rsp);
pdu_ctrl_rx->llctrl.opcode = PDU_DATA_LLCTRL_TYPE_FEATURE_RSP;
(void)memset(&pdu_ctrl_rx->llctrl.feature_rsp.features[0], 0x00,
sizeof(pdu_ctrl_rx->llctrl.feature_rsp.features));
pdu_ctrl_rx->llctrl.feature_req.features[0] =
conn->llcp_features & 0xFF;
pdu_ctrl_rx->llctrl.feature_req.features[1] =
(conn->llcp_features >> 8) & 0xFF;
pdu_ctrl_rx->llctrl.feature_req.features[2] =
(conn->llcp_features >> 16) & 0xFF;
/* enqueue feature rsp structure into rx queue */
packet_rx_enqueue();
return;
}
node_tx = mem_acquire(&_radio.pkt_tx_ctrl_free);
if (node_tx) {
struct pdu_data *pdu_ctrl_tx = (void *)node_tx->pdu_data;
@@ -7295,8 +7346,8 @@ static inline void event_conn_param_req(struct connection *conn,
sizeof(struct pdu_data_llctrl_conn_param_req);
pdu_ctrl_tx->llctrl.opcode = PDU_DATA_LLCTRL_TYPE_CONN_PARAM_REQ;
p = (void *)&pdu_ctrl_tx->llctrl.conn_param_req;
p->interval_min = conn->llcp_conn_param.interval;
p->interval_max = conn->llcp_conn_param.interval;
p->interval_min = conn->llcp_conn_param.interval_min;
p->interval_max = conn->llcp_conn_param.interval_max;
p->latency = conn->llcp_conn_param.latency;
p->timeout = conn->llcp_conn_param.timeout;
p->preferred_periodicity = 0;
@@ -7404,13 +7455,13 @@ static inline void event_conn_param_rsp(struct connection *conn)
conn->llcp.conn_upd.win_offset_us = 0;
if (conn->llcp_conn_param.preferred_periodicity) {
conn->llcp.conn_upd.interval =
((conn->llcp_conn_param.interval /
((conn->llcp_conn_param.interval_min /
conn->llcp_conn_param.preferred_periodicity) +
1) *
conn->llcp_conn_param.preferred_periodicity;
} else {
conn->llcp.conn_upd.interval =
conn->llcp_conn_param.interval;
conn->llcp_conn_param.interval_max;
}
conn->llcp.conn_upd.latency = conn->llcp_conn_param.latency;
conn->llcp.conn_upd.timeout = conn->llcp_conn_param.timeout;
@@ -7436,8 +7487,8 @@ static inline void event_conn_param_rsp(struct connection *conn)
sizeof(struct pdu_data_llctrl_conn_param_rsp);
pdu->llctrl.opcode = PDU_DATA_LLCTRL_TYPE_CONN_PARAM_RSP;
rsp = (void *)&pdu->llctrl.conn_param_rsp;
rsp->interval_min = conn->llcp_conn_param.interval;
rsp->interval_max = conn->llcp_conn_param.interval;
rsp->interval_min = conn->llcp_conn_param.interval_min;
rsp->interval_max = conn->llcp_conn_param.interval_max;
rsp->latency = conn->llcp_conn_param.latency;
rsp->timeout = conn->llcp_conn_param.timeout;
rsp->preferred_periodicity =
@@ -7491,8 +7542,8 @@ static inline void event_conn_param_app_req(struct connection *conn)
sizeof(struct pdu_data_llctrl_conn_param_req);
pdu->llctrl.opcode = PDU_DATA_LLCTRL_TYPE_CONN_PARAM_REQ;
p = (void *) &pdu->llctrl.conn_param_req;
p->interval_min = conn->llcp_conn_param.interval;
p->interval_max = conn->llcp_conn_param.interval;
p->interval_min = conn->llcp_conn_param.interval_min;
p->interval_max = conn->llcp_conn_param.interval_max;
p->latency = conn->llcp_conn_param.latency;
p->timeout = conn->llcp_conn_param.timeout;
@@ -7655,11 +7706,9 @@ static inline void event_len_prep(struct connection *conn)
/* Procedure complete */
conn->llcp_length.ack = conn->llcp_length.req;
conn->llcp_length.pause_tx = 0;
conn->procedure_expire = 0;
/* resume data packet tx */
_radio.conn_curr->pause_tx = 0;
/* Use the new rx octets/time in the connection */
conn->max_rx_octets = conn->llcp_length.rx_octets;
@@ -7834,6 +7883,11 @@ static inline void event_phy_req_prep(struct connection *conn)
case LLCP_PHY_STATE_UPD:
{
/* Defer if another procedure in progress */
if (conn->llcp_ack != conn->llcp_req) {
return;
}
/* Procedure complete */
conn->llcp_phy.ack = conn->llcp_phy.req;
@@ -7919,7 +7973,6 @@ static inline void event_phy_upd_ind_prep(struct connection *conn,
/* generate phy update event */
if (conn->llcp.phy_upd_ind.cmd) {
struct radio_pdu_node_rx *node_rx;
struct pdu_data *pdu_data;
node_rx = packet_rx_reserve_get(2);
LL_ASSERT(node_rx);
@@ -7928,8 +7981,7 @@ static inline void event_phy_upd_ind_prep(struct connection *conn,
node_rx->hdr.type =
NODE_RX_TYPE_PHY_UPDATE;
pdu_data = (void *)&node_rx->pdu_data;
upd = (void *)pdu_data->lldata;
upd = (void *)&node_rx->pdu_data;
upd->status = 0;
upd->tx = conn->phy_tx;
upd->rx = conn->phy_rx;
@@ -7962,7 +8014,6 @@ static inline void event_phy_upd_ind_prep(struct connection *conn,
} else if (((event_counter - conn->llcp.phy_upd_ind.instant) & 0xFFFF)
<= 0x7FFF) {
struct radio_pdu_node_rx *node_rx;
struct pdu_data *pdu_data;
u8_t old_tx, old_rx;
/* procedure request acked */
@@ -7991,8 +8042,7 @@ static inline void event_phy_upd_ind_prep(struct connection *conn,
node_rx->hdr.handle = conn->handle;
node_rx->hdr.type = NODE_RX_TYPE_PHY_UPDATE;
pdu_data = (void *)&node_rx->pdu_data;
upd = (void *)pdu_data->lldata;
upd = (void *)&node_rx->pdu_data;
upd->status = 0;
upd->tx = conn->phy_tx;
upd->rx = conn->phy_rx;
@@ -8642,7 +8692,11 @@ static void prepare_pdu_data_tx(struct connection *conn,
/* no ctrl or data packet */
!conn->pkt_tx_head ||
/* data tx paused, only control packets allowed */
(conn->pause_tx && (conn->pkt_tx_head != conn->pkt_tx_ctrl))) {
((conn->pause_tx ||
#if defined(CONFIG_BT_CTLR_DATA_LENGTH)
conn->llcp_length.pause_tx ||
#endif /* CONFIG_BT_CTLR_DATA_LENGTH */
0) && (conn->pkt_tx_head != conn->pkt_tx_ctrl))) {
_pdu_data_tx = empty_tx_enqueue(conn);
} else {
u16_t max_tx_octets;
@@ -9253,7 +9307,8 @@ static u32_t conn_update_req(struct connection *conn)
BIT(BT_LE_FEAT_BIT_CONN_PARAM_REQ)))) {
/** Perform slave intiated conn param req */
conn->llcp_conn_param.status = 0;
conn->llcp_conn_param.interval = conn->conn_interval;
conn->llcp_conn_param.interval_min = conn->conn_interval;
conn->llcp_conn_param.interval_max = conn->conn_interval;
conn->llcp_conn_param.latency = conn->latency;
conn->llcp_conn_param.timeout = conn->conn_interval *
conn->supervision_reload *
@@ -9271,15 +9326,19 @@ static u32_t conn_update_req(struct connection *conn)
}
#endif /* CONFIG_BT_CTLR_XTAL_ADVANCED && CONFIG_BT_CTLR_SCHED_ADVANCED */
static u32_t chan_map_update(struct connection *conn,
struct pdu_data *pdu_data_rx)
static u8_t chan_map_update(struct connection *conn,
struct pdu_data *pdu_data_rx)
{
if (((pdu_data_rx->llctrl.chan_map_ind.instant -
conn->event_counter) & 0xffff) > 0x7fff) {
return 1;
return BT_HCI_ERR_INSTANT_PASSED;
}
/* different transaction collision */
if (conn->llcp_req != conn->llcp_ack) {
return BT_HCI_ERR_DIFF_TRANS_COLLISION;
}
LL_ASSERT(conn->llcp_req == conn->llcp_ack);
memcpy(&conn->llcp.chan_map.chm[0],
&pdu_data_rx->llctrl.chan_map_ind.chm[0],
@@ -9327,7 +9386,7 @@ static inline u8_t phy_upd_ind_recv(struct radio_pdu_node_rx *node_rx,
/* generate phy update complete event */
node_rx->hdr.type = NODE_RX_TYPE_PHY_UPDATE;
upd = (void *)pdu_data_rx->lldata;
upd = (void *)pdu_data_rx;
upd->status = 0;
upd->tx = conn->phy_tx;
upd->rx = conn->phy_rx;
@@ -10162,6 +10221,7 @@ u32_t radio_adv_enable(u16_t interval, u8_t chan_map, u8_t filter_policy,
#if defined(CONFIG_BT_CTLR_DATA_LENGTH)
conn->llcp_length.req = 0;
conn->llcp_length.ack = 0;
conn->llcp_length.pause_tx = 0;
#endif /* CONFIG_BT_CTLR_DATA_LENGTH */
#if defined(CONFIG_BT_CTLR_PHY)
@@ -10473,33 +10533,25 @@ u32_t radio_scan_enable(u8_t type, u8_t init_addr_type, u8_t *init_addr,
return 0;
}
u32_t radio_scan_disable(void)
u32_t radio_scan_disable(bool scanner)
{
u32_t status;
if (scanner && _radio.scanner.conn) {
return BT_HCI_ERR_CMD_DISALLOWED;
}
status = role_disable(RADIO_TICKER_ID_SCAN,
RADIO_TICKER_ID_SCAN_STOP);
if (!status) {
struct connection *conn;
if (!status && !_radio.scanner.conn) {
_radio.scanner.is_enabled = 0;
if (!_radio.advertiser.is_enabled) {
ll_adv_scan_state_cb(0);
}
conn = _radio.scanner.conn;
if (conn) {
_radio.scanner.conn = NULL;
mem_release(conn->llcp_terminate.
radio_pdu_node_rx.hdr.onion.link,
&_radio.link_rx_free);
mem_release(conn, &_radio.conn_free);
}
}
return status ? BT_HCI_ERR_CMD_DISALLOWED : 0;
return _radio.scanner.is_enabled ? BT_HCI_ERR_CMD_DISALLOWED : 0;
}
u32_t ll_scan_is_enabled(void)
@@ -10644,6 +10696,7 @@ u32_t radio_connect_enable(u8_t adv_addr_type, u8_t *adv_addr, u16_t interval,
#if defined(CONFIG_BT_CTLR_DATA_LENGTH)
conn->llcp_length.req = 0;
conn->llcp_length.ack = 0;
conn->llcp_length.pause_tx = 0;
#endif /* CONFIG_BT_CTLR_DATA_LENGTH */
#if defined(CONFIG_BT_CTLR_PHY)
@@ -10681,7 +10734,7 @@ u32_t radio_connect_enable(u8_t adv_addr_type, u8_t *adv_addr, u16_t interval,
return 0;
}
u32_t ll_connect_disable(void)
u32_t ll_connect_disable(void **node_rx)
{
u32_t status;
@@ -10689,13 +10742,27 @@ u32_t ll_connect_disable(void)
return BT_HCI_ERR_CMD_DISALLOWED;
}
status = radio_scan_disable();
status = radio_scan_disable(false);
if (!status) {
struct connection *conn = _radio.scanner.conn;
struct radio_pdu_node_rx *rx;
rx = (void *)&conn->llcp_terminate.radio_pdu_node_rx;
/* free the memq link early, as caller could overwrite it */
mem_release(rx->hdr.onion.link, &_radio.link_rx_free);
rx->hdr.type = NODE_RX_TYPE_CONNECTION;
rx->hdr.handle = 0xffff;
*((u8_t *)rx->pdu_data) = BT_HCI_ERR_UNKNOWN_CONN_ID;
*node_rx = rx;
}
return status;
}
u32_t ll_conn_update(u16_t handle, u8_t cmd, u8_t status, u16_t interval,
u16_t latency, u16_t timeout)
u32_t ll_conn_update(u16_t handle, u8_t cmd, u8_t status, u16_t interval_min,
u16_t interval_max, u16_t latency, u16_t timeout)
{
struct connection *conn;
@@ -10728,7 +10795,7 @@ u32_t ll_conn_update(u16_t handle, u8_t cmd, u8_t status, u16_t interval,
conn->llcp.conn_upd.win_size = 1;
conn->llcp.conn_upd.win_offset_us = 0;
conn->llcp.conn_upd.interval = interval;
conn->llcp.conn_upd.interval = interval_max;
conn->llcp.conn_upd.latency = latency;
conn->llcp.conn_upd.timeout = timeout;
/* conn->llcp.conn_upd.instant = 0; */
@@ -10759,7 +10826,8 @@ u32_t ll_conn_update(u16_t handle, u8_t cmd, u8_t status, u16_t interval,
}
conn->llcp_conn_param.status = 0;
conn->llcp_conn_param.interval = interval;
conn->llcp_conn_param.interval_min = interval_min;
conn->llcp_conn_param.interval_max = interval_max;
conn->llcp_conn_param.latency = latency;
conn->llcp_conn_param.timeout = timeout;
conn->llcp_conn_param.state = cmd;
@@ -11323,11 +11391,9 @@ void ll_rx_dequeue(void)
if (node_rx->hdr.type == NODE_RX_TYPE_CONNECTION) {
struct radio_le_conn_cmplt *radio_le_conn_cmplt;
struct connection *conn = NULL;
struct pdu_data *pdu_data_rx;
u8_t bm;
pdu_data_rx = (void *)node_rx->pdu_data;
radio_le_conn_cmplt = (void *)pdu_data_rx->lldata;
radio_le_conn_cmplt = (void *)node_rx->pdu_data;
if ((radio_le_conn_cmplt->status == BT_HCI_ERR_ADV_TIMEOUT) ||
radio_le_conn_cmplt->role) {
if (radio_le_conn_cmplt->status ==
@@ -11374,6 +11440,27 @@ void ll_rx_mem_release(void **node_rx)
_node_rx = _node_rx->hdr.onion.next;
switch (_node_rx_free->hdr.type) {
case NODE_RX_TYPE_CONNECTION:
if (IS_ENABLED(CONFIG_BT_CENTRAL)) {
if (*((u8_t *)_node_rx_free->pdu_data) ==
BT_HCI_ERR_UNKNOWN_CONN_ID) {
struct connection *conn;
conn = _radio.scanner.conn;
_radio.scanner.conn = NULL;
mem_release(conn, &_radio.conn_free);
_radio.scanner.is_enabled = 0;
if (!_radio.advertiser.is_enabled) {
ll_adv_scan_state_cb(0);
}
break;
}
}
/* passthrough */
case NODE_RX_TYPE_DC_PDU:
case NODE_RX_TYPE_REPORT:
@@ -11386,7 +11473,6 @@ void ll_rx_mem_release(void **node_rx)
case NODE_RX_TYPE_SCAN_REQ:
#endif /* CONFIG_BT_CTLR_SCAN_REQ_NOTIFY */
case NODE_RX_TYPE_CONNECTION:
case NODE_RX_TYPE_CONN_UPDATE:
case NODE_RX_TYPE_ENC_REFRESH:

View File

@@ -356,7 +356,7 @@ u32_t radio_adv_filter_pol_get(void);
u32_t radio_scan_enable(u8_t type, u8_t init_addr_type, u8_t *init_addr,
u16_t interval, u16_t window, u8_t filter_policy,
u8_t rpa_gen, u8_t rl_idx);
u32_t radio_scan_disable(void);
u32_t radio_scan_disable(bool scanner);
u32_t ll_scan_is_enabled(void);
u32_t radio_scan_filter_pol_get(void);

View File

@@ -210,7 +210,8 @@ struct connection {
u8_t cmd:1;
u8_t disabled:1;
u8_t status;
u16_t interval;
u16_t interval_min;
u16_t interval_max;
u16_t latency;
u16_t timeout;
u8_t preferred_periodicity;
@@ -236,6 +237,7 @@ struct connection {
#define LLCP_LENGTH_STATE_ACK_WAIT 1
#define LLCP_LENGTH_STATE_RSP_WAIT 2
#define LLCP_LENGTH_STATE_RESIZE 3
u8_t pause_tx:1;
u16_t rx_octets;
u16_t tx_octets;
#if defined(CONFIG_BT_CTLR_PHY)

View File

@@ -9,6 +9,7 @@
#include <zephyr/types.h>
#include <bluetooth/hci.h>
#include <bluetooth/controller.h>
#include <misc/slist.h>
#include "util/util.h"
@@ -55,3 +56,8 @@ u32_t ll_addr_set(u8_t addr_type, u8_t const *const bdaddr)
return 0;
}
void bt_ctlr_set_public_addr(const u8_t *addr)
{
(void)memcpy(pub_addr, addr, sizeof(pub_addr));
}

View File

@@ -59,12 +59,22 @@ u32_t ll_scan_params_set(u8_t type, u16_t interval, u16_t window,
u32_t ll_scan_enable(u8_t enable)
{
u8_t rpa_gen = 0;
u32_t status;
u8_t rpa_gen = 0;
u32_t scan;
if (!enable) {
return radio_scan_disable();
} else if (ll_scan_is_enabled()) {
return radio_scan_disable(true);
}
scan = ll_scan_is_enabled();
/* Initiator and scanning are not supported */
if (scan & BIT(2)) {
return BT_HCI_ERR_CMD_DISALLOWED;
}
if (scan) {
/* Duplicate filtering is processed in the HCI layer */
return 0;
}

View File

@@ -244,6 +244,7 @@ config BT_ATT_TX_MAX
config BT_AUTO_PHY_UPDATE
bool "Auto-initiate PHY Update Procedure"
depends on BT_PHY_UPDATE
default y
help
Initiate PHY Update Procedure on connection establishment.
@@ -258,6 +259,7 @@ config BT_SMP
select TINYCRYPT_AES
select TINYCRYPT_AES_CMAC
select BT_RPA
select BT_ECC
help
This option enables support for the Security Manager Protocol
(SMP), making it possible to pair devices over LE.
@@ -311,6 +313,14 @@ config BT_USE_DEBUG_KEYS
If this option is enabled anyone is able to decipher encrypted air
traffic.
config BT_BONDABLE
bool "Bondable Mode"
default y
help
This option enables support for Bondable Mode. In this mode,
Bonding flag in AuthReq of SMP Pairing Request/Response will be set
indicating the support for this mode.
endif # BT_SMP
config BT_L2CAP_DYNAMIC_CHANNEL
@@ -341,8 +351,61 @@ config BT_MAX_PAIRED
Maximum number of paired Bluetooth devices. The minimum (and
default) number is 1.
config BT_GAP_PERIPHERAL_PREF_PARAMS
bool "Configure peripheral preferred connection parameters"
default y
depends on BT_PERIPHERAL
help
This allows to configure periphral preferred connection parameters.
Enabling this option results in adding PPCP characteristic in GAP
and sending request for connection parameters udpate after GAP
recommended 5 seconds of connection as peripheral. If disabled it is
up to application to set expected connection parameters.
if BT_GAP_PERIPHERAL_PREF_PARAMS
config BT_PERIPHERAL_PREF_MIN_INT
int "Peripheral preferred minimum connection interval in 1.25ms units"
default 24
range 6 3200
config BT_PERIPHERAL_PREF_MAX_INT
int "Peripheral preferred maximum connection interval in 1.25ms units"
default 40
range 6 3200
config BT_PERIPHERAL_PREF_SLAVE_LATENCY
int "Peripheral preferred slave latency in Connection Intervals"
default 0
range 0 499
config BT_PERIPHERAL_PREF_TIMEOUT
int "Peripheral preferred supervision timeout in 10ms units"
default 42
range 10 3200
help
It is up to user to provide valid timeout which pass required minimum
value: in milliseconds it shall be larger than
"(1+ Conn_Latency) * Conn_Interval_Max * 2"
where Conn_Interval_Max is given in milliseconds.
endif # BT_GAP_PERIPHERAL_PREF_PARAMS
config BT_CREATE_CONN_TIMEOUT
int "Timeout for pending LE Create Connection command in seconds"
default 3
range 1 65535
endif # BT_CONN
if BT_OBSERVER
config BT_BACKGROUND_SCAN_INTERVAL
int "Scan interval used for background scanning in 0.625 ms units"
default 2048
range 4 16384
config BT_BACKGROUND_SCAN_WINDOW
int "Scan window used for background scanning in 0.625 ms units"
default 18
range 4 16384
endif # BT_OBSERVER
config BT_SCAN_WITH_IDENTITY
bool "Perform active scanning using local identity address"
depends on !BT_PRIVACY && (BT_CENTRAL || BT_OBSERVER)
@@ -402,12 +465,17 @@ config BT_ID_MAX
endif # BT_HCI_HOST
config BT_ECC
bool "Enable ECDH key generation support"
help
This option adds support for ECDH HCI commands.
config BT_TINYCRYPT_ECC
bool "Use TinyCrypt library for ECDH"
select TINYCRYPT
select TINYCRYPT_ECC_DH
depends on BT_HCI_RAW || BT_HCI_HOST
default y if BT_CTLR && (BT_SMP || BT_MESH_PROV)
depends on BT_ECC && (BT_HCI_RAW || BT_HCI_HOST)
default y if BT_CTLR
help
If this option is set TinyCrypt library is used for emulating the
ECDH HCI commands and events needed by e.g. LE Secure Connections.

View File

@@ -337,6 +337,7 @@ process:
return 0;
}
#if defined(CONFIG_BT_GATT_CLIENT)
static u8_t att_mtu_rsp(struct bt_att *att, struct net_buf *buf)
{
struct bt_att_exchange_mtu_rsp *rsp;
@@ -370,6 +371,7 @@ static u8_t att_mtu_rsp(struct bt_att *att, struct net_buf *buf)
return att_handle_rsp(att, rsp, buf->len, 0);
}
#endif /* CONFIG_BT_GATT_CLIENT */
static bool range_is_valid(u16_t start, u16_t end, u16_t *err)
{
@@ -1298,9 +1300,9 @@ static u8_t prep_write_cb(const struct bt_gatt_attr *attr, void *user_data)
return BT_GATT_ITER_STOP;
}
/* Check if attribute requires handler to accept the data */
if (!(attr->perm & BT_GATT_PERM_PREPARE_WRITE)) {
data->err = BT_ATT_ERR_WRITE_NOT_PERMITTED;
return BT_GATT_ITER_STOP;
goto append;
}
/* Write attribute value to check if device is authorized */
@@ -1311,6 +1313,7 @@ static u8_t prep_write_cb(const struct bt_gatt_attr *attr, void *user_data)
return BT_GATT_ITER_STOP;
}
append:
/* Copy data into the outstanding queue */
data->buf = net_buf_alloc(&prep_pool, K_NO_WAIT);
if (!data->buf) {
@@ -1503,6 +1506,7 @@ static u8_t att_signed_write_cmd(struct bt_att *att, struct net_buf *buf)
}
#endif /* CONFIG_BT_SIGNING */
#if defined(CONFIG_BT_GATT_CLIENT)
#if defined(CONFIG_BT_SMP)
static int att_change_security(struct bt_conn *conn, u8_t err)
{
@@ -1647,6 +1651,13 @@ static u8_t att_handle_read_mult_rsp(struct bt_att *att, struct net_buf *buf)
}
#endif /* CONFIG_BT_GATT_READ_MULTIPLE */
static u8_t att_handle_read_group_rsp(struct bt_att *att, struct net_buf *buf)
{
BT_DBG("");
return att_handle_rsp(att, buf->data, buf->len, 0);
}
static u8_t att_handle_write_rsp(struct bt_att *att, struct net_buf *buf)
{
BT_DBG("");
@@ -1703,6 +1714,7 @@ static u8_t att_indicate(struct bt_att *att, struct net_buf *buf)
return 0;
}
#endif /* CONFIG_BT_GATT_CLIENT */
static u8_t att_confirm(struct bt_att *att, struct net_buf *buf)
{
@@ -1717,69 +1729,35 @@ static const struct att_handler {
att_type_t type;
u8_t (*func)(struct bt_att *att, struct net_buf *buf);
} handlers[] = {
{ BT_ATT_OP_ERROR_RSP,
sizeof(struct bt_att_error_rsp),
ATT_RESPONSE,
att_error_rsp },
{ BT_ATT_OP_MTU_REQ,
sizeof(struct bt_att_exchange_mtu_req),
ATT_REQUEST,
att_mtu_req },
{ BT_ATT_OP_MTU_RSP,
sizeof(struct bt_att_exchange_mtu_rsp),
ATT_RESPONSE,
att_mtu_rsp },
{ BT_ATT_OP_FIND_INFO_REQ,
sizeof(struct bt_att_find_info_req),
ATT_REQUEST,
att_find_info_req },
{ BT_ATT_OP_FIND_INFO_RSP,
sizeof(struct bt_att_find_info_rsp),
ATT_RESPONSE,
att_handle_find_info_rsp },
{ BT_ATT_OP_FIND_TYPE_REQ,
sizeof(struct bt_att_find_type_req),
ATT_REQUEST,
att_find_type_req },
{ BT_ATT_OP_FIND_TYPE_RSP,
sizeof(struct bt_att_find_type_rsp),
ATT_RESPONSE,
att_handle_find_type_rsp },
{ BT_ATT_OP_READ_TYPE_REQ,
sizeof(struct bt_att_read_type_req),
ATT_REQUEST,
att_read_type_req },
{ BT_ATT_OP_READ_TYPE_RSP,
sizeof(struct bt_att_read_type_rsp),
ATT_RESPONSE,
att_handle_read_type_rsp },
{ BT_ATT_OP_READ_REQ,
sizeof(struct bt_att_read_req),
ATT_REQUEST,
att_read_req },
{ BT_ATT_OP_READ_RSP,
sizeof(struct bt_att_read_rsp),
ATT_RESPONSE,
att_handle_read_rsp },
{ BT_ATT_OP_READ_BLOB_REQ,
sizeof(struct bt_att_read_blob_req),
ATT_REQUEST,
att_read_blob_req },
{ BT_ATT_OP_READ_BLOB_RSP,
sizeof(struct bt_att_read_blob_rsp),
ATT_RESPONSE,
att_handle_read_blob_rsp },
#if defined(CONFIG_BT_GATT_READ_MULTIPLE)
{ BT_ATT_OP_READ_MULT_REQ,
BT_ATT_READ_MULT_MIN_LEN_REQ,
ATT_REQUEST,
att_read_mult_req },
#endif /* CONFIG_BT_GATT_READ_MULTIPLE */
#if defined(CONFIG_BT_GATT_READ_MULTIPLE)
{ BT_ATT_OP_READ_MULT_RSP,
sizeof(struct bt_att_read_mult_rsp),
ATT_RESPONSE,
att_handle_read_mult_rsp },
#endif /* CONFIG_BT_GATT_READ_MULTIPLE */
{ BT_ATT_OP_READ_GROUP_REQ,
sizeof(struct bt_att_read_group_req),
@@ -1789,34 +1767,14 @@ static const struct att_handler {
sizeof(struct bt_att_write_req),
ATT_REQUEST,
att_write_req },
{ BT_ATT_OP_WRITE_RSP,
0,
ATT_RESPONSE,
att_handle_write_rsp },
{ BT_ATT_OP_PREPARE_WRITE_REQ,
sizeof(struct bt_att_prepare_write_req),
ATT_REQUEST,
att_prepare_write_req },
{ BT_ATT_OP_PREPARE_WRITE_RSP,
sizeof(struct bt_att_prepare_write_rsp),
ATT_RESPONSE,
att_handle_prepare_write_rsp },
{ BT_ATT_OP_EXEC_WRITE_REQ,
sizeof(struct bt_att_exec_write_req),
ATT_REQUEST,
att_exec_write_req },
{ BT_ATT_OP_EXEC_WRITE_RSP,
0,
ATT_RESPONSE,
att_handle_exec_write_rsp },
{ BT_ATT_OP_NOTIFY,
sizeof(struct bt_att_notify),
ATT_NOTIFICATION,
att_notify },
{ BT_ATT_OP_INDICATE,
sizeof(struct bt_att_indicate),
ATT_INDICATION,
att_indicate },
{ BT_ATT_OP_CONFIRM,
0,
ATT_CONFIRMATION,
@@ -1832,6 +1790,66 @@ static const struct att_handler {
ATT_COMMAND,
att_signed_write_cmd },
#endif /* CONFIG_BT_SIGNING */
#if defined(CONFIG_BT_GATT_CLIENT)
{ BT_ATT_OP_ERROR_RSP,
sizeof(struct bt_att_error_rsp),
ATT_RESPONSE,
att_error_rsp },
{ BT_ATT_OP_MTU_RSP,
sizeof(struct bt_att_exchange_mtu_rsp),
ATT_RESPONSE,
att_mtu_rsp },
{ BT_ATT_OP_FIND_INFO_RSP,
sizeof(struct bt_att_find_info_rsp),
ATT_RESPONSE,
att_handle_find_info_rsp },
{ BT_ATT_OP_FIND_TYPE_RSP,
sizeof(struct bt_att_find_type_rsp),
ATT_RESPONSE,
att_handle_find_type_rsp },
{ BT_ATT_OP_READ_TYPE_RSP,
sizeof(struct bt_att_read_type_rsp),
ATT_RESPONSE,
att_handle_read_type_rsp },
{ BT_ATT_OP_READ_RSP,
sizeof(struct bt_att_read_rsp),
ATT_RESPONSE,
att_handle_read_rsp },
{ BT_ATT_OP_READ_BLOB_RSP,
sizeof(struct bt_att_read_blob_rsp),
ATT_RESPONSE,
att_handle_read_blob_rsp },
#if defined(CONFIG_BT_GATT_READ_MULTIPLE)
{ BT_ATT_OP_READ_MULT_RSP,
sizeof(struct bt_att_read_mult_rsp),
ATT_RESPONSE,
att_handle_read_mult_rsp },
#endif /* CONFIG_BT_GATT_READ_MULTIPLE */
{ BT_ATT_OP_READ_GROUP_RSP,
sizeof(struct bt_att_read_group_rsp),
ATT_RESPONSE,
att_handle_read_group_rsp },
{ BT_ATT_OP_WRITE_RSP,
0,
ATT_RESPONSE,
att_handle_write_rsp },
{ BT_ATT_OP_PREPARE_WRITE_RSP,
sizeof(struct bt_att_prepare_write_rsp),
ATT_RESPONSE,
att_handle_prepare_write_rsp },
{ BT_ATT_OP_EXEC_WRITE_RSP,
0,
ATT_RESPONSE,
att_handle_exec_write_rsp },
{ BT_ATT_OP_NOTIFY,
sizeof(struct bt_att_notify),
ATT_NOTIFICATION,
att_notify },
{ BT_ATT_OP_INDICATE,
sizeof(struct bt_att_indicate),
ATT_INDICATION,
att_indicate },
#endif /* CONFIG_BT_GATT_CLIENT */
};
static att_type_t att_op_get_type(u8_t op)

View File

@@ -57,7 +57,7 @@ NET_BUF_POOL_FIXED_DEFINE(frag_pool, CONFIG_BT_L2CAP_TX_FRAG_COUNT, FRAG_SIZE,
#endif /* CONFIG_BT_L2CAP_TX_FRAG_COUNT > 0 */
/* How long until we cancel HCI_LE_Create_Connection */
#define CONN_TIMEOUT K_SECONDS(3)
#define CONN_TIMEOUT K_SECONDS(CONFIG_BT_CREATE_CONN_TIMEOUT)
#if defined(CONFIG_BT_SMP) || defined(CONFIG_BT_BREDR)
const struct bt_conn_auth_cb *bt_auth;
@@ -150,6 +150,17 @@ void notify_le_param_updated(struct bt_conn *conn)
{
struct bt_conn_cb *cb;
/* If new connection parameters meet requirement of pending
* parameters don't send slave conn param request anymore on timeout
*/
if (atomic_test_bit(conn->flags, BT_CONN_SLAVE_PARAM_SET) &&
conn->le.interval >= conn->le.interval_min &&
conn->le.interval <= conn->le.interval_max &&
conn->le.latency == conn->le.pending_latency &&
conn->le.timeout == conn->le.pending_timeout) {
atomic_clear_bit(conn->flags, BT_CONN_SLAVE_PARAM_SET);
}
for (cb = callback_list; cb; cb = cb->_next) {
if (cb->le_param_updated) {
cb->le_param_updated(conn, conn->le.interval,
@@ -188,25 +199,88 @@ bool le_param_req(struct bt_conn *conn, struct bt_le_conn_param *param)
return true;
}
static void le_conn_update(struct k_work *work)
static int send_conn_le_param_update(struct bt_conn *conn,
const struct bt_le_conn_param *param)
{
BT_DBG("conn %p features 0x%02x params (%d-%d %d %d)", conn,
conn->le.features[0], param->interval_min,
param->interval_max, param->latency, param->timeout);
/* Use LE connection parameter request if both local and remote support
* it; or if local role is master then use LE connection update.
*/
if ((BT_FEAT_LE_CONN_PARAM_REQ_PROC(bt_dev.le.features) &&
BT_FEAT_LE_CONN_PARAM_REQ_PROC(conn->le.features) &&
!atomic_test_bit(conn->flags, BT_CONN_SLAVE_PARAM_L2CAP)) ||
(conn->role == BT_HCI_ROLE_MASTER)) {
int rc;
rc = bt_conn_le_conn_update(conn, param);
/* store those in case of fallback to L2CAP */
if (rc == 0) {
conn->le.pending_latency = param->latency;
conn->le.pending_timeout = param->timeout;
}
return rc;
}
/* If remote master does not support LL Connection Parameters Request
* Procedure
*/
return bt_l2cap_update_conn_param(conn, param);
}
static void conn_le_update_timeout(struct k_work *work)
{
struct bt_conn_le *le = CONTAINER_OF(work, struct bt_conn_le,
update_work);
struct bt_conn *conn = CONTAINER_OF(le, struct bt_conn, le);
const struct bt_le_conn_param *param;
BT_DBG("conn %p", conn);
if (IS_ENABLED(CONFIG_BT_CENTRAL) &&
conn->state == BT_CONN_CONNECT) {
bt_conn_disconnect(conn, BT_HCI_ERR_REMOTE_USER_TERM_CONN);
conn->role == BT_CONN_ROLE_MASTER) {
/* we don't call bt_conn_disconnect as it would also clear
* auto connect flag if it was set, instead just cancel
* connection directly
*/
bt_hci_cmd_send(BT_HCI_OP_LE_CREATE_CONN_CANCEL, NULL);
return;
}
param = BT_LE_CONN_PARAM(conn->le.interval_min,
conn->le.interval_max,
conn->le.latency,
conn->le.timeout);
#if defined (CONFIG_BT_GAP_PERIPHERAL_PREF_PARAMS)
/* if application set own params use those, otherwise use defaults */
if (atomic_test_and_clear_bit(conn->flags, BT_CONN_SLAVE_PARAM_SET)) {
param = BT_LE_CONN_PARAM(conn->le.interval_min,
conn->le.interval_max,
conn->le.pending_latency,
conn->le.pending_timeout);
bt_conn_le_param_update(conn, param);
send_conn_le_param_update(conn, param);
} else {
param = BT_LE_CONN_PARAM(CONFIG_BT_PERIPHERAL_PREF_MIN_INT,
CONFIG_BT_PERIPHERAL_PREF_MAX_INT,
CONFIG_BT_PERIPHERAL_PREF_SLAVE_LATENCY,
CONFIG_BT_PERIPHERAL_PREF_TIMEOUT);
send_conn_le_param_update(conn, param);
}
#else
/* update only if application set own params */
if (atomic_test_and_clear_bit(conn->flags, BT_CONN_SLAVE_PARAM_SET)) {
param = BT_LE_CONN_PARAM(conn->le.interval_min,
conn->le.interval_max,
conn->le.latency,
conn->le.timeout);
send_conn_le_param_update(conn, param);
}
#endif
atomic_set_bit(conn->flags, BT_CONN_SLAVE_PARAM_UPDATE);
}
static struct bt_conn *conn_new(void)
@@ -1383,7 +1457,7 @@ struct bt_conn *bt_conn_add_le(const bt_addr_le_t *peer)
conn->type = BT_CONN_TYPE_LE;
conn->le.interval_min = BT_GAP_INIT_CONN_INT_MIN;
conn->le.interval_max = BT_GAP_INIT_CONN_INT_MAX;
k_delayed_work_init(&conn->le.update_work, le_conn_update);
k_delayed_work_init(&conn->le.update_work, conn_le_update_timeout);
return conn;
}
@@ -1735,25 +1809,30 @@ int bt_conn_le_param_update(struct bt_conn *conn,
conn->le.interval <= param->interval_max &&
conn->le.latency == param->latency &&
conn->le.timeout == param->timeout) {
atomic_clear_bit(conn->flags, BT_CONN_SLAVE_PARAM_SET);
return -EALREADY;
}
/* Cancel any pending update */
k_delayed_work_cancel(&conn->le.update_work);
/* Use LE connection parameter request if both local and remote support
* it; or if local role is master then use LE connection update.
*/
if ((BT_FEAT_LE_CONN_PARAM_REQ_PROC(bt_dev.le.features) &&
BT_FEAT_LE_CONN_PARAM_REQ_PROC(conn->le.features)) ||
(conn->role == BT_HCI_ROLE_MASTER)) {
return bt_conn_le_conn_update(conn, param);
if (IS_ENABLED(CONFIG_BT_CENTRAL) &&
conn->role == BT_CONN_ROLE_MASTER) {
return send_conn_le_param_update(conn, param);
}
/* If remote master does not support LL Connection Parameters Request
* Procedure
*/
return bt_l2cap_update_conn_param(conn, param);
if (IS_ENABLED(CONFIG_BT_PERIPHERAL)) {
/* if slave conn param update timer expired just send request */
if (atomic_test_bit(conn->flags, BT_CONN_SLAVE_PARAM_UPDATE)) {
return send_conn_le_param_update(conn, param);
}
/* store new conn params to be used by update timer */
conn->le.interval_min = param->interval_min;
conn->le.interval_max = param->interval_max;
conn->le.pending_latency = param->latency;
conn->le.pending_timeout = param->timeout;
atomic_set_bit(conn->flags, BT_CONN_SLAVE_PARAM_SET);
}
return 0;
}
int bt_conn_disconnect(struct bt_conn *conn, u8_t reason)
@@ -1857,7 +1936,7 @@ struct bt_conn *bt_conn_create_le(const bt_addr_le_t *peer,
return conn;
}
int bt_le_set_auto_conn(bt_addr_le_t *addr,
int bt_le_set_auto_conn(const bt_addr_le_t *addr,
const struct bt_le_conn_param *param)
{
struct bt_conn *conn;

View File

@@ -25,7 +25,9 @@ enum {
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 */
BT_CONN_SLAVE_PARAM_UPDATE, /* If slave param update timer fired */
BT_CONN_SLAVE_PARAM_SET, /* If slave param were set from app */
BT_CONN_SLAVE_PARAM_L2CAP, /* If should force L2CAP for CPUP */
/* Total number of flags - must be at the end of the enum */
BT_CONN_NUM_FLAGS,
@@ -43,6 +45,8 @@ struct bt_conn_le {
u16_t latency;
u16_t timeout;
u16_t pending_latency;
u16_t pending_timeout;
u8_t features[8];

View File

@@ -100,6 +100,27 @@ static ssize_t read_appearance(struct bt_conn *conn,
sizeof(appearance));
}
#if defined (CONFIG_BT_GAP_PERIPHERAL_PREF_PARAMS)
static ssize_t read_ppcp(struct bt_conn *conn, const struct bt_gatt_attr *attr,
void *buf, u16_t len, u16_t offset)
{
struct __packed {
uint16_t min_int;
uint16_t max_int;
uint16_t latency;
uint16_t timeout;
} ppcp;
ppcp.min_int = sys_cpu_to_le16(CONFIG_BT_PERIPHERAL_PREF_MIN_INT);
ppcp.max_int = sys_cpu_to_le16(CONFIG_BT_PERIPHERAL_PREF_MAX_INT);
ppcp.latency = sys_cpu_to_le16(CONFIG_BT_PERIPHERAL_PREF_SLAVE_LATENCY);
ppcp.timeout = sys_cpu_to_le16(CONFIG_BT_PERIPHERAL_PREF_TIMEOUT);
return bt_gatt_attr_read(conn, attr, buf, len, offset, &ppcp,
sizeof(ppcp));
}
#endif
#if defined(CONFIG_BT_CENTRAL) && defined(CONFIG_BT_PRIVACY)
static ssize_t read_central_addr_res(struct bt_conn *conn,
const struct bt_gatt_attr *attr, void *buf,
@@ -131,6 +152,10 @@ static struct bt_gatt_attr gap_attrs[] = {
BT_GATT_CHRC_READ, BT_GATT_PERM_READ,
read_central_addr_res, NULL, NULL),
#endif /* CONFIG_BT_CENTRAL && CONFIG_BT_PRIVACY */
#if defined(CONFIG_BT_GAP_PERIPHERAL_PREF_PARAMS)
BT_GATT_CHARACTERISTIC(BT_UUID_GAP_PPCP, BT_GATT_CHRC_READ,
BT_GATT_PERM_READ, read_ppcp, NULL, NULL),
#endif
};
static struct bt_gatt_service gap_svc = BT_GATT_SERVICE(gap_attrs);
@@ -145,6 +170,11 @@ static void sc_ccc_cfg_changed(const struct bt_gatt_attr *attr,
static struct bt_gatt_attr gatt_attrs[] = {
BT_GATT_PRIMARY_SERVICE(BT_UUID_GATT),
/* Bluetooth 5.0, Vol3 Part G:
* The Service Changed characteristic Attribute Handle on the server
* shall not change if the server has a trusted relationship with any
* client.
*/
BT_GATT_CHARACTERISTIC(BT_UUID_GATT_SC, BT_GATT_CHRC_INDICATE,
BT_GATT_PERM_NONE, NULL, NULL, NULL),
BT_GATT_CCC(sc_ccc_cfg, sc_ccc_cfg_changed),
@@ -260,8 +290,8 @@ void bt_gatt_init(void)
}
/* Register mandatory services */
gatt_register(&gap_svc);
gatt_register(&gatt_svc);
gatt_register(&gap_svc);
k_delayed_work_init(&gatt_sc.work, sc_process);
}
@@ -1573,6 +1603,137 @@ static int gatt_read_type(struct bt_conn *conn,
return gatt_send(conn, buf, gatt_read_type_rsp, params, NULL);
}
static u16_t parse_service(struct bt_conn *conn, const void *pdu,
struct bt_gatt_discover_params *params,
u16_t length)
{
const struct bt_att_read_group_rsp *rsp = pdu;
u16_t start_handle, end_handle = 0;
union {
struct bt_uuid uuid;
struct bt_uuid_16 u16;
struct bt_uuid_128 u128;
} u;
/* Data can be either in UUID16 or UUID128 */
switch (rsp->len) {
case 6: /* UUID16 */
u.uuid.type = BT_UUID_TYPE_16;
break;
case 20: /* UUID128 */
u.uuid.type = BT_UUID_TYPE_128;
break;
default:
BT_ERR("Invalid data len %u", rsp->len);
goto done;
}
/* Parse services found */
for (length--, pdu = rsp->data; length >= rsp->len;
length -= rsp->len, pdu += rsp->len) {
struct bt_gatt_attr attr = {};
struct bt_gatt_service_val value;
const struct bt_att_group_data *data = pdu;
start_handle = sys_le16_to_cpu(data->start_handle);
if (!start_handle) {
goto done;
}
end_handle = sys_le16_to_cpu(data->end_handle);
if (!end_handle || end_handle < start_handle) {
goto done;
}
switch (u.uuid.type) {
case BT_UUID_TYPE_16:
memcpy(&u.u16.val, data->value, sizeof(u.u16.val));
u.u16.val = sys_le16_to_cpu(u.u16.val);
break;
case BT_UUID_TYPE_128:
memcpy(u.u128.val, data->value, sizeof(u.u128.val));
break;
}
BT_DBG("start_handle 0x%04x end_handle 0x%04x uuid %s",
start_handle, end_handle, bt_uuid_str(&u.uuid));
if (params->type == BT_GATT_DISCOVER_PRIMARY) {
attr.uuid = BT_UUID_GATT_PRIMARY;
} else {
attr.uuid = BT_UUID_GATT_SECONDARY;
}
value.end_handle = end_handle;
value.uuid = &u.uuid;
attr.handle = start_handle;
attr.user_data = &value;
if (params->func(conn, &attr, params) == BT_GATT_ITER_STOP) {
return 0;
}
}
/* Whole PDU read without error */
if (length == 0 && end_handle) {
return end_handle;
}
done:
params->func(conn, NULL, params);
return 0;
}
static void gatt_read_group_rsp(struct bt_conn *conn, u8_t err,
const void *pdu, u16_t length,
void *user_data)
{
struct bt_gatt_discover_params *params = user_data;
u16_t handle;
BT_DBG("err 0x%02x", err);
if (err) {
params->func(conn, NULL, params);
return;
}
handle = parse_service(conn, pdu, params, length);
if (!handle) {
return;
}
gatt_discover_next(conn, handle, params);
}
static int gatt_read_group(struct bt_conn *conn,
struct bt_gatt_discover_params *params)
{
struct net_buf *buf;
struct bt_att_read_group_req *req;
buf = bt_att_create_pdu(conn, BT_ATT_OP_READ_GROUP_REQ, sizeof(*req));
if (!buf) {
return -ENOMEM;
}
req = net_buf_add(buf, sizeof(*req));
req->start_handle = sys_cpu_to_le16(params->start_handle);
req->end_handle = sys_cpu_to_le16(params->end_handle);
if (params->type == BT_GATT_DISCOVER_PRIMARY) {
net_buf_add_le16(buf, BT_UUID_16(BT_UUID_GATT_PRIMARY)->val);
} else {
net_buf_add_le16(buf, BT_UUID_16(BT_UUID_GATT_SECONDARY)->val);
}
BT_DBG("start_handle 0x%04x end_handle 0x%04x", params->start_handle,
params->end_handle);
return gatt_send(conn, buf, gatt_read_group_rsp, params, NULL);
}
static void gatt_find_info_rsp(struct bt_conn *conn, u8_t err,
const void *pdu, u16_t length,
void *user_data)
@@ -1696,7 +1857,10 @@ int bt_gatt_discover(struct bt_conn *conn,
switch (params->type) {
case BT_GATT_DISCOVER_PRIMARY:
case BT_GATT_DISCOVER_SECONDARY:
return gatt_find_type(conn, params);
if (params->uuid) {
return gatt_find_type(conn, params);
}
return gatt_read_group(conn, params);
case BT_GATT_DISCOVER_INCLUDE:
case BT_GATT_DISCOVER_CHARACTERISTIC:
return gatt_read_type(conn, params);
@@ -2277,14 +2441,6 @@ int bt_gatt_store_ccc(u8_t id, const bt_addr_le_t *addr)
bt_gatt_foreach_attr(0x0001, 0xffff, ccc_save, &save);
str = settings_str_from_bytes(save.store,
save.count * sizeof(*save.store),
val, sizeof(val));
if (!str) {
BT_ERR("Unable to encode CCC as handle:value");
return -EINVAL;
}
if (id) {
char id_str[4];
@@ -2296,6 +2452,21 @@ int bt_gatt_store_ccc(u8_t id, const bt_addr_le_t *addr)
(bt_addr_le_t *)addr, NULL);
}
if (!save.count) {
/* No entries to encode just clear */
str = NULL;
goto save;
}
str = settings_str_from_bytes(save.store,
save.count * sizeof(*save.store),
val, sizeof(val));
if (!str) {
BT_ERR("Unable to encode CCC as handle:value");
return -EINVAL;
}
save:
err = settings_save_one(key, str);
if (err) {
BT_ERR("Failed to store CCCs (err %d)", err);
@@ -2303,7 +2474,7 @@ int bt_gatt_store_ccc(u8_t id, const bt_addr_le_t *addr)
}
BT_DBG("Stored CCCs for %s (%s) val %s", bt_addr_le_str(addr), key,
str);
str ? str : "nill");
return 0;
}
@@ -2385,13 +2556,16 @@ static u8_t ccc_load(const struct bt_gatt_attr *attr, void *user_data)
BT_DBG("Restoring CCC: handle 0x%04x value 0x%04x", load->entry->handle,
load->entry->value);
cfg = ccc_find_cfg(ccc, BT_ADDR_LE_ANY);
cfg = ccc_find_cfg(ccc, &load->addr);
if (!cfg) {
BT_DBG("Unable to restore CCC: no cfg left");
goto next;
cfg = ccc_find_cfg(ccc, BT_ADDR_LE_ANY);
if (!cfg) {
BT_DBG("Unable to restore CCC: no cfg left");
goto next;
}
bt_addr_le_copy(&cfg->peer, &load->addr);
}
bt_addr_le_copy(&cfg->peer, &load->addr);
cfg->value = load->entry->value;
next:

View File

@@ -82,9 +82,11 @@ static bt_ready_cb_t ready_cb;
static bt_le_scan_cb_t *scan_dev_found_cb;
#if defined(CONFIG_BT_ECC)
static u8_t pub_key[64];
static struct bt_pub_key_cb *pub_key_cb;
static bt_dh_key_cb_t dh_key_cb;
#endif /* CONFIG_BT_ECC */
#if defined(CONFIG_BT_BREDR)
static bt_br_discovery_cb_t *discovery_cb;
@@ -680,7 +682,10 @@ static int hci_le_read_remote_features(struct bt_conn *conn)
return 0;
}
static int hci_le_set_data_len(struct bt_conn *conn)
/* LE Data Length Change Event is optional so this function just ignore
* error and stack will continue to use default values.
*/
static void hci_le_set_data_len(struct bt_conn *conn)
{
struct bt_hci_rp_le_read_max_data_len *rp;
struct bt_hci_cp_le_set_data_len *cp;
@@ -690,7 +695,8 @@ static int hci_le_set_data_len(struct bt_conn *conn)
err = bt_hci_cmd_send_sync(BT_HCI_OP_LE_READ_MAX_DATA_LEN, NULL, &rsp);
if (err) {
return err;
BT_ERR("Failed to read DLE max data len");
return;
}
rp = (void *)rsp->data;
@@ -700,7 +706,8 @@ static int hci_le_set_data_len(struct bt_conn *conn)
buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_DATA_LEN, sizeof(*cp));
if (!buf) {
return -ENOBUFS;
BT_ERR("Failed to create LE Set Data Length Command");
return;
}
cp = net_buf_add(buf, sizeof(*cp));
@@ -709,10 +716,8 @@ static int hci_le_set_data_len(struct bt_conn *conn)
cp->tx_time = sys_cpu_to_le16(tx_time);
err = bt_hci_cmd_send(BT_HCI_OP_LE_SET_DATA_LEN, buf);
if (err) {
return err;
BT_ERR("Failed to send LE Set Data Length Command");
}
return 0;
}
static int hci_le_set_phy(struct bt_conn *conn)
@@ -736,16 +741,23 @@ static int hci_le_set_phy(struct bt_conn *conn)
return 0;
}
static void update_conn_param(struct bt_conn *conn)
static void slave_update_conn_param(struct bt_conn *conn)
{
if (!IS_ENABLED(CONFIG_BT_PERIPHERAL)) {
return;
}
/* don't start timer again on PHY update etc */
if (atomic_test_bit(conn->flags, BT_CONN_SLAVE_PARAM_UPDATE)) {
return;
}
/*
* Core 4.2 Vol 3, Part C, 9.3.12.2
* The Peripheral device should not perform a Connection Parameter
* Update procedure within 5 s after establishing a connection.
*/
k_delayed_work_submit(&conn->le.update_work,
conn->role == BT_HCI_ROLE_MASTER ? K_NO_WAIT :
CONN_UPDATE_TIMEOUT);
k_delayed_work_submit(&conn->le.update_work, CONN_UPDATE_TIMEOUT);
}
#if defined(CONFIG_BT_SMP)
@@ -781,30 +793,33 @@ static void le_enh_conn_complete(struct bt_hci_evt_le_enh_conn_complete *evt)
}
#endif
if (evt->status) {
/*
* if there was an error we are only interested in pending
* connection so there is no need to check ID address as
* only one connection can be in that state
*
* Depending on error code address might not be valid anyway.
*/
conn = bt_conn_lookup_state_le(NULL, BT_CONN_CONNECT);
if (!conn) {
return;
if (IS_ENABLED(CONFIG_BT_CENTRAL)) {
if (evt->status) {
/*
* if there was an error we are only interested in pending
* connection so there is no need to check ID address as
* only one connection can be in that state
*
* Depending on error code address might not be valid anyway.
*/
conn = bt_conn_lookup_state_le(NULL, BT_CONN_CONNECT);
if (!conn) {
return;
}
conn->err = evt->status;
bt_conn_set_state(conn, BT_CONN_DISCONNECTED);
/* check if device is market for auto connect */
if (atomic_test_bit(conn->flags, BT_CONN_AUTO_CONNECT)) {
bt_conn_set_state(conn, BT_CONN_CONNECT_SCAN);
}
goto done;
}
conn->err = evt->status;
bt_conn_set_state(conn, BT_CONN_DISCONNECTED);
/* Drop the reference got by lookup call in CONNECT state.
* We are now in DISCONNECTED state since no successful LE
* link been made.
*/
bt_conn_unref(conn);
return;
} else {
BT_ASSERT(evt->status == 0);
}
bt_addr_le_copy(&id_addr, &evt->peer_addr);
@@ -849,6 +864,7 @@ static void le_enh_conn_complete(struct bt_hci_evt_le_enh_conn_complete *evt)
conn->le.latency = sys_le16_to_cpu(evt->latency);
conn->le.timeout = sys_le16_to_cpu(evt->supv_timeout);
conn->role = evt->role;
conn->err = 0;
/*
* Use connection address (instead of identity address) as initiator
@@ -910,15 +926,15 @@ static void le_enh_conn_complete(struct bt_hci_evt_le_enh_conn_complete *evt)
}
}
if (BT_FEAT_LE_DLE(bt_dev.le.features)) {
err = hci_le_set_data_len(conn);
if (!err) {
atomic_set_bit(conn->flags, BT_CONN_AUTO_DATA_LEN);
goto done;
}
if (IS_ENABLED(CONFIG_BT_DATA_LEN_UPDATE) &&
BT_FEAT_LE_DLE(bt_dev.le.features)) {
hci_le_set_data_len(conn);
}
update_conn_param(conn);
if (IS_ENABLED(CONFIG_BT_PERIPHERAL) &&
conn->role == BT_CONN_ROLE_SLAVE) {
slave_update_conn_param(conn);
}
done:
bt_conn_unref(conn);
@@ -998,23 +1014,22 @@ static void le_remote_feat_complete(struct net_buf *buf)
}
}
if (BT_FEAT_LE_DLE(bt_dev.le.features) &&
if (IS_ENABLED(CONFIG_BT_DATA_LEN_UPDATE) &&
BT_FEAT_LE_DLE(bt_dev.le.features) &&
BT_FEAT_LE_DLE(conn->le.features)) {
int err;
err = hci_le_set_data_len(conn);
if (!err) {
atomic_set_bit(conn->flags, BT_CONN_AUTO_DATA_LEN);
goto done;
}
hci_le_set_data_len(conn);
}
update_conn_param(conn);
if (IS_ENABLED(CONFIG_BT_PERIPHERAL) &&
conn->role == BT_CONN_ROLE_SLAVE) {
slave_update_conn_param(conn);
}
done:
bt_conn_unref(conn);
}
#if defined(CONFIG_BT_DATA_LEN_UPDATE)
static void le_data_len_change(struct net_buf *buf)
{
struct bt_hci_evt_le_data_len_change *evt = (void *)buf->data;
@@ -1034,16 +1049,13 @@ static void le_data_len_change(struct net_buf *buf)
BT_DBG("max. tx: %u (%uus), max. rx: %u (%uus)", max_tx_octets,
max_tx_time, max_rx_octets, max_rx_time);
if (!atomic_test_and_clear_bit(conn->flags, BT_CONN_AUTO_DATA_LEN)) {
goto done;
}
/* TODO use those */
update_conn_param(conn);
done:
bt_conn_unref(conn);
}
#endif /* CONFIG_BT_DATA_LEN_UPDATE */
#if defined(CONFIG_BT_PHY_UPDATE)
static void le_phy_update_complete(struct net_buf *buf)
{
struct bt_hci_evt_le_phy_update_complete *evt = (void *)buf->data;
@@ -1064,22 +1076,21 @@ static void le_phy_update_complete(struct net_buf *buf)
goto done;
}
if (BT_FEAT_LE_DLE(bt_dev.le.features) &&
if (IS_ENABLED(CONFIG_BT_DATA_LEN_UPDATE) &&
BT_FEAT_LE_DLE(bt_dev.le.features) &&
BT_FEAT_LE_DLE(conn->le.features)) {
int err;
err = hci_le_set_data_len(conn);
if (!err) {
atomic_set_bit(conn->flags, BT_CONN_AUTO_DATA_LEN);
goto done;
}
hci_le_set_data_len(conn);
}
update_conn_param(conn);
if (IS_ENABLED(CONFIG_BT_PERIPHERAL) &&
conn->role == BT_CONN_ROLE_SLAVE) {
slave_update_conn_param(conn);
}
done:
bt_conn_unref(conn);
}
#endif /* CONFIG_BT_PHY_UPDATE */
bool bt_le_conn_params_valid(const struct bt_le_conn_param *param)
{
@@ -1197,6 +1208,18 @@ static void le_conn_update_complete(struct net_buf *buf)
conn->le.latency = sys_le16_to_cpu(evt->latency);
conn->le.timeout = sys_le16_to_cpu(evt->supv_timeout);
notify_le_param_updated(conn);
} else if (evt->status == BT_HCI_ERR_UNSUPP_REMOTE_FEATURE &&
conn->role == BT_HCI_ROLE_SLAVE &&
!atomic_test_and_set_bit(conn->flags,
BT_CONN_SLAVE_PARAM_L2CAP)) {
struct bt_le_conn_param param;
param.interval_min = conn->le.interval_min;
param.interval_max = conn->le.interval_max;
param.latency = conn->le.pending_latency;
param.timeout = conn->le.pending_timeout;
bt_l2cap_update_conn_param(conn, &param);
}
bt_conn_unref(conn);
@@ -1574,6 +1597,7 @@ static void conn_complete(struct net_buf *buf)
}
conn->handle = handle;
conn->err = 0;
conn->encrypt = evt->encr_enabled;
update_sec_level_br(conn);
bt_conn_set_state(conn, BT_CONN_CONNECTED);
@@ -2652,7 +2676,7 @@ static void update_sec_level(struct bt_conn *conn)
}
if (conn->le.keys && (conn->le.keys->flags & BT_KEYS_AUTHENTICATED)) {
if (conn->le.keys->keys & BT_KEYS_LTK_P256) {
if (conn->le.keys->flags & BT_KEYS_SC) {
conn->sec_level = BT_SECURITY_FIPS;
} else {
conn->sec_level = BT_SECURITY_HIGH;
@@ -2913,6 +2937,7 @@ done:
}
#endif /* CONFIG_BT_SMP */
#if defined(CONFIG_BT_ECC)
static void le_pkey_complete(struct net_buf *buf)
{
struct bt_hci_evt_le_p256_public_key_complete *evt = (void *)buf->data;
@@ -2943,6 +2968,7 @@ static void le_dhkey_complete(struct net_buf *buf)
dh_key_cb = NULL;
}
}
#endif /* CONFIG_BT_ECC */
static void hci_reset_complete(struct net_buf *buf)
{
@@ -3075,6 +3101,8 @@ static int start_le_scan(u8_t scan_type, u16_t interval, u16_t window)
}
set_param.addr_type = BT_ADDR_LE_RANDOM;
} else if (set_param.addr_type == BT_ADDR_LE_RANDOM) {
set_random_address(&bt_dev.id_addr[0].a);
}
}
@@ -3121,6 +3149,13 @@ int bt_le_scan_update(bool fast_scan)
u16_t interval, window;
struct bt_conn *conn;
/* don't restart scan if we have pending connection */
conn = bt_conn_lookup_state_le(NULL, BT_CONN_CONNECT);
if (conn) {
bt_conn_unref(conn);
return 0;
}
conn = bt_conn_lookup_state_le(NULL, BT_CONN_CONNECT_SCAN);
if (!conn) {
return 0;
@@ -3134,8 +3169,8 @@ int bt_le_scan_update(bool fast_scan)
interval = BT_GAP_SCAN_FAST_INTERVAL;
window = BT_GAP_SCAN_FAST_WINDOW;
} else {
interval = BT_GAP_SCAN_SLOW_INTERVAL_1;
window = BT_GAP_SCAN_SLOW_WINDOW_1;
interval = CONFIG_BT_BACKGROUND_SCAN_INTERVAL;
window = CONFIG_BT_BACKGROUND_SCAN_WINDOW;
}
return start_le_scan(BT_HCI_LE_SCAN_PASSIVE, interval, window);
@@ -3254,24 +3289,30 @@ static void hci_le_meta_event(struct net_buf *buf)
case BT_HCI_EVT_LE_CONN_PARAM_REQ:
le_conn_param_req(buf);
break;
#if defined(CONFIG_BT_DATA_LEN_UPDATE)
case BT_HCI_EVT_LE_DATA_LEN_CHANGE:
le_data_len_change(buf);
break;
#endif /* CONFIG_BT_DATA_LEN_UPDATE */
#if defined(CONFIG_BT_PHY_UPDATE)
case BT_HCI_EVT_LE_PHY_UPDATE_COMPLETE:
le_phy_update_complete(buf);
break;
#endif /* CONFIG_BT_PHY_UPDATE */
#endif /* CONFIG_BT_CONN */
#if defined(CONFIG_BT_SMP)
case BT_HCI_EVT_LE_LTK_REQUEST:
le_ltk_request(buf);
break;
#endif /* CONFIG_BT_SMP */
#if defined(CONFIG_BT_ECC)
case BT_HCI_EVT_LE_P256_PUBLIC_KEY_COMPLETE:
le_pkey_complete(buf);
break;
case BT_HCI_EVT_LE_GENERATE_DHKEY_COMPLETE:
le_dhkey_complete(buf);
break;
#endif /* CONFIG_BT_SMP */
#if defined(CONFIG_BT_OBSERVER)
case BT_HCI_EVT_LE_ADVERTISING_REPORT:
le_adv_report(buf);
@@ -3740,12 +3781,14 @@ static int le_set_event_mask(void)
mask |= BT_EVT_MASK_LE_CONN_PARAM_REQ;
}
if (BT_FEAT_LE_DLE(bt_dev.le.features)) {
if (IS_ENABLED(CONFIG_BT_DATA_LEN_UPDATE) &&
BT_FEAT_LE_DLE(bt_dev.le.features)) {
mask |= BT_EVT_MASK_LE_DATA_LEN_CHANGE;
}
if (BT_FEAT_LE_PHY_2M(bt_dev.le.features) ||
BT_FEAT_LE_PHY_CODED(bt_dev.le.features)) {
if (IS_ENABLED(CONFIG_BT_PHY_UPDATE) &&
(BT_FEAT_LE_PHY_2M(bt_dev.le.features) ||
BT_FEAT_LE_PHY_CODED(bt_dev.le.features))) {
mask |= BT_EVT_MASK_LE_PHY_UPDATE_COMPLETE;
}
}
@@ -3759,7 +3802,8 @@ static int le_set_event_mask(void)
* If "LE Read Local P-256 Public Key" and "LE Generate DH Key" are
* supported we need to enable events generated by those commands.
*/
if ((bt_dev.supported_commands[34] & 0x02) &&
if (IS_ENABLED(CONFIG_BT_ECC) &&
(bt_dev.supported_commands[34] & 0x02) &&
(bt_dev.supported_commands[34] & 0x04)) {
mask |= BT_EVT_MASK_LE_P256_PUBLIC_KEY_COMPLETE;
mask |= BT_EVT_MASK_LE_GENERATE_DHKEY_COMPLETE;
@@ -3832,6 +3876,7 @@ static int le_init(void)
}
if (IS_ENABLED(CONFIG_BT_CONN) &&
IS_ENABLED(CONFIG_BT_DATA_LEN_UPDATE) &&
BT_FEAT_LE_DLE(bt_dev.le.features)) {
struct bt_hci_cp_le_write_default_data_len *cp;
struct bt_hci_rp_le_read_max_data_len *rp;
@@ -4191,49 +4236,6 @@ int bt_addr_le_create_static(bt_addr_le_t *addr)
return 0;
}
int bt_setup_id_addr(void)
{
#if defined(CONFIG_BT_HCI_VS_EXT)
/* Check for VS_Read_Static_Addresses support. Only read the
* addresses if the user has not already configured one or
* more identities (!bt_dev.id_count).
*/
if (!bt_dev.id_count && (bt_dev.vs_commands[1] & BIT(0))) {
struct bt_hci_rp_vs_read_static_addrs *rp;
struct net_buf *rsp;
int err, i;
err = bt_hci_cmd_send_sync(BT_HCI_OP_VS_READ_STATIC_ADDRS,
NULL, &rsp);
if (err) {
BT_WARN("Failed to read static addresses");
goto generate;
}
rp = (void *)rsp->data;
bt_dev.id_count = min(rp->num_addrs, CONFIG_BT_ID_MAX);
for (i = 0; i < bt_dev.id_count; i++) {
bt_dev.id_addr[i].type = BT_ADDR_LE_RANDOM;
bt_addr_copy(&bt_dev.id_addr[i].a, &rp->a[i].bdaddr);
}
net_buf_unref(rsp);
if (bt_dev.id_count) {
return set_random_address(&bt_dev.id_addr[0].a);
}
BT_WARN("No static addresses stored in controller");
} else {
BT_WARN("Read Static Addresses command not available");
}
generate:
#endif
return bt_id_create(NULL, NULL);
}
#if defined(CONFIG_BT_DEBUG)
static const char *ver_str(u8_t ver)
{
@@ -4867,7 +4869,7 @@ static void id_create(u8_t id, bt_addr_le_t *addr, u8_t *irk)
}
#if defined(CONFIG_BT_PRIVACY)
if (atomic_test_bit(bt_dev.flags, BT_DEV_READY)) {
{
u8_t zero_irk[16] = { 0 };
if (irk && memcmp(irk, zero_irk, 16)) {
@@ -5005,6 +5007,64 @@ int bt_id_delete(u8_t id)
return 0;
}
#if defined(CONFIG_BT_HCI_VS_EXT)
static uint8_t bt_read_static_addr(bt_addr_le_t *addr)
{
struct bt_hci_rp_vs_read_static_addrs *rp;
struct net_buf *rsp;
int err, i;
u8_t cnt;
if (!(bt_dev.vs_commands[1] & BIT(0))) {
BT_WARN("Read Static Addresses command not available");
return 0;
}
err = bt_hci_cmd_send_sync(BT_HCI_OP_VS_READ_STATIC_ADDRS, NULL, &rsp);
if (err) {
BT_WARN("Failed to read static addresses");
return 0;
}
rp = (void *)rsp->data;
cnt = min(rp->num_addrs, CONFIG_BT_ID_MAX);
for (i = 0; i < cnt; i++) {
addr[i].type = BT_ADDR_LE_RANDOM;
bt_addr_copy(&addr[i].a, &rp->a[i].bdaddr);
}
net_buf_unref(rsp);
if (!cnt) {
BT_WARN("No static addresses stored in controller");
}
return cnt;
}
#elif defined(CONFIG_BT_CTLR)
uint8_t bt_read_static_addr(bt_addr_le_t *addr);
#endif /* CONFIG_BT_HCI_VS_EXT */
int bt_setup_id_addr(void)
{
#if defined(CONFIG_BT_HCI_VS_EXT) || defined(CONFIG_BT_CTLR)
/* Only read the addresses if the user has not already configured one or
* more identities (!bt_dev.id_count).
*/
if (!bt_dev.id_count) {
bt_addr_le_t addrs[CONFIG_BT_ID_MAX];
bt_dev.id_count = bt_read_static_addr(addrs);
if (bt_dev.id_count) {
int i;
for (i = 0; i < bt_dev.id_count; i++) {
id_create(i, &addrs[i], NULL);
}
return set_random_address(&bt_dev.id_addr[0].a);
}
}
#endif
return bt_id_create(NULL, NULL);
}
bool bt_addr_le_is_bonded(u8_t id, const bt_addr_le_t *addr)
{
if (IS_ENABLED(CONFIG_BT_SMP)) {
@@ -5559,6 +5619,7 @@ u16_t bt_hci_get_cmd_opcode(struct net_buf *buf)
return cmd(buf)->opcode;
}
#if defined(CONFIG_BT_ECC)
int bt_pub_key_gen(struct bt_pub_key_cb *new_cb)
{
struct bt_pub_key_cb *cb;
@@ -5644,6 +5705,7 @@ int bt_dh_key_gen(const u8_t remote_pk[64], bt_dh_key_cb_t cb)
return 0;
}
#endif /* CONFIG_BT_ECC */
#if defined(CONFIG_BT_BREDR)
int bt_br_oob_get_local(struct bt_br_oob *oob)

View File

@@ -113,8 +113,9 @@ static u8_t generate_keys(void)
/* 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);
sys_memcpy_swap(&ecc.pk, debug_public_key, 32);
sys_memcpy_swap(&ecc.pk[32], &debug_public_key[32], 32);
sys_memcpy_swap(ecc.private_key, debug_private_key, 32);
#endif
return 0;
}

View File

@@ -24,6 +24,7 @@ enum {
BT_KEYS_DEBUG = BIT(1),
BT_KEYS_ID_PENDING_ADD = BIT(2),
BT_KEYS_ID_PENDING_DEL = BIT(3),
BT_KEYS_SC = BIT(4),
};
struct bt_ltk {

View File

@@ -719,6 +719,20 @@ static void l2cap_chan_destroy(struct bt_l2cap_chan *chan)
}
}
static u16_t le_err_to_result(int err)
{
switch (err) {
case -ENOMEM:
return BT_L2CAP_LE_ERR_NO_RESOURCES;
case -EACCES:
return BT_L2CAP_LE_ERR_AUTHORIZATION;
case -EPERM:
return BT_L2CAP_LE_ERR_KEY_SIZE;
default:
return BT_L2CAP_LE_ERR_UNACCEPT_PARAMS;
}
}
static void le_conn_req(struct bt_l2cap *l2cap, u8_t ident,
struct net_buf *buf)
{
@@ -728,6 +742,7 @@ static void le_conn_req(struct bt_l2cap *l2cap, u8_t ident,
struct bt_l2cap_le_conn_req *req = (void *)buf->data;
struct bt_l2cap_le_conn_rsp *rsp;
u16_t psm, scid, mtu, mps, credits;
int err;
if (buf->len < sizeof(*req)) {
BT_ERR("Too small LE conn req packet size");
@@ -757,34 +772,33 @@ static void le_conn_req(struct bt_l2cap *l2cap, u8_t ident,
/* Check if there is a server registered */
server = l2cap_server_lookup_psm(psm);
if (!server) {
rsp->result = sys_cpu_to_le16(BT_L2CAP_ERR_PSM_NOT_SUPP);
rsp->result = sys_cpu_to_le16(BT_L2CAP_LE_ERR_PSM_NOT_SUPP);
goto rsp;
}
/* Check if connection has minimum required security level */
if (conn->sec_level < server->sec_level) {
rsp->result = sys_cpu_to_le16(BT_L2CAP_ERR_AUTHENTICATION);
rsp->result = sys_cpu_to_le16(BT_L2CAP_LE_ERR_AUTHENTICATION);
goto rsp;
}
if (!L2CAP_LE_CID_IS_DYN(scid)) {
rsp->result = sys_cpu_to_le16(BT_L2CAP_ERR_INVALID_SCID);
rsp->result = sys_cpu_to_le16(BT_L2CAP_LE_ERR_INVALID_SCID);
goto rsp;
}
chan = bt_l2cap_le_lookup_tx_cid(conn, scid);
if (chan) {
rsp->result = sys_cpu_to_le16(BT_L2CAP_ERR_SCID_IN_USE);
rsp->result = sys_cpu_to_le16(BT_L2CAP_LE_ERR_SCID_IN_USE);
goto rsp;
}
/* Request server to accept the new connection and allocate the
* channel.
*
* TODO: Handle different errors, it may be required to respond async.
*/
if (server->accept(conn, &chan) < 0) {
rsp->result = sys_cpu_to_le16(BT_L2CAP_ERR_NO_RESOURCES);
err = server->accept(conn, &chan);
if (err < 0) {
rsp->result = sys_cpu_to_le16(le_err_to_result(err));
goto rsp;
}
@@ -820,9 +834,9 @@ static void le_conn_req(struct bt_l2cap *l2cap, u8_t ident,
rsp->mps = sys_cpu_to_le16(ch->rx.mps);
rsp->mtu = sys_cpu_to_le16(ch->rx.mtu);
rsp->credits = sys_cpu_to_le16(ch->rx.init_credits);
rsp->result = BT_L2CAP_SUCCESS;
rsp->result = BT_L2CAP_LE_SUCCESS;
} else {
rsp->result = sys_cpu_to_le16(BT_L2CAP_ERR_NO_RESOURCES);
rsp->result = sys_cpu_to_le16(BT_L2CAP_LE_ERR_NO_RESOURCES);
}
rsp:
bt_l2cap_send(conn, BT_L2CAP_CID_LE_SIG, buf);
@@ -896,13 +910,13 @@ static void le_disconn_req(struct bt_l2cap *l2cap, u8_t ident,
static int l2cap_change_security(struct bt_l2cap_le_chan *chan, u16_t err)
{
switch (err) {
case BT_L2CAP_ERR_ENCRYPTION:
case BT_L2CAP_LE_ERR_ENCRYPTION:
if (chan->chan.required_sec_level >= BT_SECURITY_MEDIUM) {
return -EALREADY;
}
chan->chan.required_sec_level = BT_SECURITY_MEDIUM;
break;
case BT_L2CAP_ERR_AUTHENTICATION:
case BT_L2CAP_LE_ERR_AUTHENTICATION:
if (chan->chan.required_sec_level < BT_SECURITY_MEDIUM) {
chan->chan.required_sec_level = BT_SECURITY_MEDIUM;
} else if (chan->chan.required_sec_level < BT_SECURITY_HIGH) {
@@ -943,9 +957,9 @@ static void le_conn_rsp(struct bt_l2cap *l2cap, u8_t ident,
mtu, mps, credits, result);
/* Keep the channel in case of security errors */
if (result == BT_L2CAP_SUCCESS ||
result == BT_L2CAP_ERR_AUTHENTICATION ||
result == BT_L2CAP_ERR_ENCRYPTION) {
if (result == BT_L2CAP_LE_SUCCESS ||
result == BT_L2CAP_LE_ERR_AUTHENTICATION ||
result == BT_L2CAP_LE_ERR_ENCRYPTION) {
chan = l2cap_lookup_ident(conn, ident);
} else {
chan = l2cap_remove_ident(conn, ident);
@@ -963,7 +977,7 @@ static void le_conn_rsp(struct bt_l2cap *l2cap, u8_t ident,
chan->chan.ident = 0;
switch (result) {
case BT_L2CAP_SUCCESS:
case BT_L2CAP_LE_SUCCESS:
chan->tx.cid = dcid;
chan->tx.mtu = mtu;
chan->tx.mps = mps;
@@ -980,8 +994,8 @@ static void le_conn_rsp(struct bt_l2cap *l2cap, u8_t ident,
l2cap_chan_rx_give_credits(chan, chan->rx.init_credits);
break;
case BT_L2CAP_ERR_AUTHENTICATION:
case BT_L2CAP_ERR_ENCRYPTION:
case BT_L2CAP_LE_ERR_AUTHENTICATION:
case BT_L2CAP_LE_ERR_ENCRYPTION:
/* If security needs changing wait it to be completed */
if (l2cap_change_security(chan, result) == 0) {
return;

View File

@@ -164,16 +164,16 @@ struct bt_l2cap_le_conn_req {
} __packed;
/* valid results in conn response on LE */
#define BT_L2CAP_SUCCESS 0x0000
#define BT_L2CAP_ERR_PSM_NOT_SUPP 0x0002
#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_ERR_UNACCEPT_PARAMS 0x000B
#define BT_L2CAP_LE_SUCCESS 0x0000
#define BT_L2CAP_LE_ERR_PSM_NOT_SUPP 0x0002
#define BT_L2CAP_LE_ERR_NO_RESOURCES 0x0004
#define BT_L2CAP_LE_ERR_AUTHENTICATION 0x0005
#define BT_L2CAP_LE_ERR_AUTHORIZATION 0x0006
#define BT_L2CAP_LE_ERR_KEY_SIZE 0x0007
#define BT_L2CAP_LE_ERR_ENCRYPTION 0x0008
#define BT_L2CAP_LE_ERR_INVALID_SCID 0x0009
#define BT_L2CAP_LE_ERR_SCID_IN_USE 0x000A
#define BT_L2CAP_LE_ERR_UNACCEPT_PARAMS 0x000B
#define BT_L2CAP_LE_CONN_RSP 0x15
struct bt_l2cap_le_conn_rsp {

View File

@@ -22,6 +22,7 @@ if BT_MESH
# Virtual option enabled whenever Generic Provisioning layer is needed
config BT_MESH_PROV
bool
select BT_ECC
config BT_MESH_PB_ADV
bool "Provisioning support using the advertising bearer (PB-ADV)"

View File

@@ -33,8 +33,8 @@
#define ADV_SCAN_UNIT(_ms) ((_ms) * 8 / 5)
/* Window and Interval are equal for continuous scanning */
#define MESH_SCAN_INTERVAL_MS 10
#define MESH_SCAN_WINDOW_MS 10
#define MESH_SCAN_INTERVAL_MS 30
#define MESH_SCAN_WINDOW_MS 30
#define MESH_SCAN_INTERVAL ADV_SCAN_UNIT(MESH_SCAN_INTERVAL_MS)
#define MESH_SCAN_WINDOW ADV_SCAN_UNIT(MESH_SCAN_WINDOW_MS)

View File

@@ -833,13 +833,7 @@ int bt_mesh_friend_req(struct bt_mesh_net_rx *rx, struct net_buf_simple *buf)
}
old_friend = sys_be16_to_cpu(msg->prev_addr);
if (BT_MESH_ADDR_IS_UNICAST(old_friend)) {
frnd = bt_mesh_friend_find(rx->sub->net_idx, old_friend,
true, false);
} else {
frnd = bt_mesh_friend_find(rx->sub->net_idx, rx->ctx.addr,
true, false);
}
frnd = bt_mesh_friend_find(rx->sub->net_idx, rx->ctx.addr, true, false);
if (frnd) {
BT_WARN("Existing LPN re-requesting Friendship");

View File

@@ -1030,7 +1030,7 @@ static void store_pending_hb_pub(void)
if (pub->dst == BT_MESH_ADDR_UNASSIGNED) {
str = NULL;
} else {
val.indefinite = (pub->count = 0xffff);
val.indefinite = (pub->count == 0xffff);
val.dst = pub->dst;
val.period = pub->period;
val.ttl = pub->ttl;

View File

@@ -72,13 +72,19 @@
#define BT_SMP_AUTH_MASK 0x07
#if defined(CONFIG_BT_BONDABLE)
#define BT_SMP_AUTH_BONDING_FLAGS BT_SMP_AUTH_BONDING
#else
#define BT_SMP_AUTH_BONDING_FLAGS 0
#endif /* CONFIG_BT_BONDABLE */
#if defined(CONFIG_BT_BREDR)
#define BT_SMP_AUTH_MASK_SC 0x2f
#define BT_SMP_AUTH_DEFAULT (BT_SMP_AUTH_BONDING | BT_SMP_AUTH_SC |\
#define BT_SMP_AUTH_DEFAULT (BT_SMP_AUTH_BONDING_FLAGS | BT_SMP_AUTH_SC |\
BT_SMP_AUTH_CT2)
#else
#define BT_SMP_AUTH_MASK_SC 0x0f
#define BT_SMP_AUTH_DEFAULT (BT_SMP_AUTH_BONDING | BT_SMP_AUTH_SC)
#define BT_SMP_AUTH_DEFAULT (BT_SMP_AUTH_BONDING_FLAGS | BT_SMP_AUTH_SC)
#endif
enum pairing_method {
@@ -243,6 +249,7 @@ static struct bt_smp_br bt_smp_br_pool[CONFIG_BT_MAX_CONN];
#endif /* CONFIG_BT_BREDR */
static struct bt_smp bt_smp_pool[CONFIG_BT_MAX_CONN];
static bool bondable = IS_ENABLED(CONFIG_BT_BONDABLE);
static bool sc_supported;
static bool sc_local_pkey_valid;
static u8_t sc_public_key[64];
@@ -2261,6 +2268,11 @@ static int smp_init(struct bt_smp *smp)
return 0;
}
void bt_set_bondable(bool enable)
{
bondable = enable;
}
static u8_t get_auth(u8_t auth)
{
if (sc_supported) {
@@ -2275,6 +2287,12 @@ static u8_t get_auth(u8_t auth)
auth |= BT_SMP_AUTH_MITM;
}
if (bondable) {
auth |= BT_SMP_AUTH_BONDING;
} else {
auth &= ~BT_SMP_AUTH_BONDING;
}
return auth;
}
@@ -4460,15 +4478,20 @@ void bt_smp_update_keys(struct bt_conn *conn)
* exclusive with legacy pairing. Other keys are added on keys
* distribution.
*/
if (atomic_test_bit(smp->flags, SMP_FLAG_SC) &&
atomic_test_bit(smp->flags, SMP_FLAG_BOND)) {
bt_keys_add_type(conn->le.keys, BT_KEYS_LTK_P256);
memcpy(conn->le.keys->ltk.val, smp->tk,
sizeof(conn->le.keys->ltk.val));
memset(conn->le.keys->ltk.rand, 0,
sizeof(conn->le.keys->ltk.rand));
memset(conn->le.keys->ltk.ediv, 0,
sizeof(conn->le.keys->ltk.ediv));
if (atomic_test_bit(smp->flags, SMP_FLAG_SC)) {
conn->le.keys->flags |= BT_KEYS_SC;
if (atomic_test_bit(smp->flags, SMP_FLAG_BOND)) {
bt_keys_add_type(conn->le.keys, BT_KEYS_LTK_P256);
memcpy(conn->le.keys->ltk.val, smp->tk,
sizeof(conn->le.keys->ltk.val));
(void)memset(conn->le.keys->ltk.rand, 0,
sizeof(conn->le.keys->ltk.rand));
(void)memset(conn->le.keys->ltk.ediv, 0,
sizeof(conn->le.keys->ltk.ediv));
}
} else {
conn->le.keys->flags &= ~BT_KEYS_SC;
}
}

View File

@@ -1142,6 +1142,26 @@ static int cmd_security(int argc, char *argv[])
return 0;
}
static int cmd_bondable(int argc, char *argv[])
{
const char *bondable;
if (argc < 2) {
return -EINVAL;
}
bondable = argv[1];
if (!strcmp(bondable, "on")) {
bt_set_bondable(true);
} else if (!strcmp(bondable, "off")) {
bt_set_bondable(false);
} else {
return -EINVAL;
}
return 0;
}
static void auth_passkey_display(struct bt_conn *conn, unsigned int passkey)
{
char addr[BT_ADDR_LE_STR_LEN];
@@ -2179,6 +2199,7 @@ static const struct shell_cmd bt_commands[] = {
{ "clear", cmd_clear },
#if defined(CONFIG_BT_SMP) || defined(CONFIG_BT_BREDR)
{ "security", cmd_security, "<security level: 0, 1, 2, 3>" },
{ "bondable", cmd_bondable, "<bondable: on, off>" },
{ "auth", cmd_auth,
"<auth method: all, input, display, yesno, confirm, none>" },
{ "auth-cancel", cmd_auth_cancel, HELP_NONE },

View File

@@ -5,8 +5,8 @@ CONFIG_BT_CTLR_CONN_PARAM_REQ=n
CONFIG_BT_CTLR_LE_PING=n
CONFIG_BT_CTLR_PRIVACY=n
CONFIG_BT_CTLR_EXT_SCAN_FP=n
CONFIG_BT_CTLR_DATA_LENGTH=n
CONFIG_BT_CTLR_PHY=n
CONFIG_BT_DATA_LEN_UPDATE=n
CONFIG_BT_PHY_UPDATE=n
CONFIG_BT_CTLR_CHAN_SEL_2=n
CONFIG_BT_CTLR_MIN_USED_CHAN=n
CONFIG_BT_CTLR_ADV_EXT=n

View File

@@ -5,8 +5,8 @@ CONFIG_BT_CTLR_CONN_PARAM_REQ=y
CONFIG_BT_CTLR_LE_PING=y
CONFIG_BT_CTLR_PRIVACY=y
CONFIG_BT_CTLR_EXT_SCAN_FP=y
CONFIG_BT_CTLR_DATA_LENGTH=y
CONFIG_BT_CTLR_PHY=y
CONFIG_BT_DATA_LEN_UPDATE=y
CONFIG_BT_PHY_UPDATE=y
CONFIG_BT_CTLR_CHAN_SEL_2=y
CONFIG_BT_CTLR_MIN_USED_CHAN=y
CONFIG_BT_CTLR_ADV_EXT=y

View File

@@ -5,8 +5,8 @@ CONFIG_BT_CTLR_CONN_PARAM_REQ=n
CONFIG_BT_CTLR_LE_PING=n
CONFIG_BT_CTLR_PRIVACY=n
CONFIG_BT_CTLR_EXT_SCAN_FP=n
CONFIG_BT_CTLR_DATA_LENGTH=n
CONFIG_BT_CTLR_PHY=n
CONFIG_BT_DATA_LEN_UPDATE=n
CONFIG_BT_PHY_UPDATE=n
CONFIG_BT_CTLR_CHAN_SEL_2=n
CONFIG_BT_CTLR_MIN_USED_CHAN=n
CONFIG_BT_CTLR_ADV_EXT=n

View File

@@ -8,8 +8,8 @@ CONFIG_BT_BROADCASTER=y
CONFIG_BT_CTLR_DUP_FILTER_LEN=0
CONFIG_BT_CTLR_LE_ENC=n
CONFIG_BT_CTLR_LE_PING=n
CONFIG_BT_CTLR_DATA_LENGTH=n
CONFIG_BT_CTLR_PHY=n
CONFIG_BT_DATA_LEN_UPDATE=n
CONFIG_BT_PHY_UPDATE=n
CONFIG_BT_CTLR_CHAN_SEL_2=n
CONFIG_BT_CTLR_MIN_USED_CHAN=n
CONFIG_BT_CTLR_ADV_EXT=n

View File

@@ -8,8 +8,8 @@ CONFIG_BT_BROADCASTER=y
CONFIG_BT_CTLR_DUP_FILTER_LEN=0
CONFIG_BT_CTLR_LE_ENC=n
CONFIG_BT_CTLR_LE_PING=n
CONFIG_BT_CTLR_DATA_LENGTH=n
CONFIG_BT_CTLR_PHY=n
CONFIG_BT_DATA_LEN_UPDATE=n
CONFIG_BT_PHY_UPDATE=n
CONFIG_BT_CTLR_CHAN_SEL_2=n
CONFIG_BT_CTLR_MIN_USED_CHAN=n
CONFIG_BT_CTLR_ADV_EXT=n

View File

@@ -8,8 +8,8 @@ CONFIG_BT_BROADCASTER=y
CONFIG_BT_CTLR_DUP_FILTER_LEN=0
CONFIG_BT_CTLR_LE_ENC=n
CONFIG_BT_CTLR_LE_PING=n
CONFIG_BT_CTLR_DATA_LENGTH=n
CONFIG_BT_CTLR_PHY=n
CONFIG_BT_DATA_LEN_UPDATE=n
CONFIG_BT_PHY_UPDATE=n
CONFIG_BT_CTLR_CHAN_SEL_2=n
CONFIG_BT_CTLR_MIN_USED_CHAN=n
CONFIG_BT_CTLR_ADV_EXT=n

View File

@@ -8,8 +8,8 @@ CONFIG_BT_BROADCASTER=y
CONFIG_BT_CTLR_DUP_FILTER_LEN=0
CONFIG_BT_CTLR_LE_ENC=n
CONFIG_BT_CTLR_LE_PING=n
CONFIG_BT_CTLR_DATA_LENGTH=n
CONFIG_BT_CTLR_PHY=n
CONFIG_BT_DATA_LEN_UPDATE=n
CONFIG_BT_PHY_UPDATE=n
CONFIG_BT_CTLR_CHAN_SEL_2=n
CONFIG_BT_CTLR_MIN_USED_CHAN=n
CONFIG_BT_CTLR_ADV_EXT=n

View File

@@ -16,8 +16,8 @@ CONFIG_BT_BROADCASTER=y
CONFIG_BT_CTLR_LE_ENC=n
CONFIG_BT_CTLR_LE_PING=n
CONFIG_BT_CTLR_DATA_LENGTH=n
CONFIG_BT_CTLR_PHY=n
CONFIG_BT_DATA_LEN_UPDATE=n
CONFIG_BT_PHY_UPDATE=n
CONFIG_BT_CTLR_CHAN_SEL_2=n
CONFIG_BT_CTLR_MIN_USED_CHAN=n
CONFIG_BT_CTLR_ADV_EXT=n

View File

@@ -24,8 +24,8 @@ CONFIG_BT_BROADCASTER=y
CONFIG_BT_CTLR_LE_ENC=n
CONFIG_BT_CTLR_LE_PING=n
CONFIG_BT_CTLR_DATA_LENGTH=n
CONFIG_BT_CTLR_PHY=n
CONFIG_BT_DATA_LEN_UPDATE=n
CONFIG_BT_PHY_UPDATE=n
CONFIG_BT_CTLR_CHAN_SEL_2=n
CONFIG_BT_CTLR_MIN_USED_CHAN=n
CONFIG_BT_CTLR_ADV_EXT=n

View File

@@ -8,8 +8,8 @@ CONFIG_BT_BROADCASTER=y
CONFIG_BT_CTLR_DUP_FILTER_LEN=0
CONFIG_BT_CTLR_LE_ENC=n
CONFIG_BT_CTLR_LE_PING=n
CONFIG_BT_CTLR_DATA_LENGTH=n
CONFIG_BT_CTLR_PHY=n
CONFIG_BT_DATA_LEN_UPDATE=n
CONFIG_BT_PHY_UPDATE=n
CONFIG_BT_CTLR_CHAN_SEL_2=n
CONFIG_BT_CTLR_MIN_USED_CHAN=n
CONFIG_BT_CTLR_ADV_EXT=n

View File

@@ -8,8 +8,8 @@ CONFIG_BT_BROADCASTER=y
CONFIG_BT_CTLR_DUP_FILTER_LEN=0
CONFIG_BT_CTLR_LE_ENC=n
CONFIG_BT_CTLR_LE_PING=n
CONFIG_BT_CTLR_DATA_LENGTH=n
CONFIG_BT_CTLR_PHY=n
CONFIG_BT_DATA_LEN_UPDATE=n
CONFIG_BT_PHY_UPDATE=n
CONFIG_BT_CTLR_CHAN_SEL_2=n
CONFIG_BT_CTLR_MIN_USED_CHAN=n
CONFIG_BT_CTLR_ADV_EXT=n

View File

@@ -8,8 +8,8 @@ CONFIG_BT_BROADCASTER=y
CONFIG_BT_CTLR_DUP_FILTER_LEN=0
CONFIG_BT_CTLR_LE_ENC=n
CONFIG_BT_CTLR_LE_PING=n
CONFIG_BT_CTLR_DATA_LENGTH=n
CONFIG_BT_CTLR_PHY=n
CONFIG_BT_DATA_LEN_UPDATE=n
CONFIG_BT_PHY_UPDATE=n
CONFIG_BT_CTLR_CHAN_SEL_2=n
CONFIG_BT_CTLR_MIN_USED_CHAN=n
CONFIG_BT_CTLR_ADV_EXT=n

View File

@@ -25,8 +25,8 @@ CONFIG_BT_DEVICE_NAME="Zephyr Mesh"
CONFIG_BT_CTLR_DUP_FILTER_LEN=0
CONFIG_BT_CTLR_LE_ENC=n
CONFIG_BT_CTLR_LE_PING=n
CONFIG_BT_CTLR_DATA_LENGTH=n
CONFIG_BT_CTLR_PHY=n
CONFIG_BT_DATA_LEN_UPDATE=n
CONFIG_BT_PHY_UPDATE=n
CONFIG_BT_CTLR_CHAN_SEL_2=n
CONFIG_BT_CTLR_MIN_USED_CHAN=n
CONFIG_BT_CTLR_ADV_EXT=n