Bluetooth: host: Add phy update procedure options

Add options for phy update procedure. User can now set no preference
option for a particular PHY as well as preference for LE Coded PHY
coding scheme.

Signed-off-by: Joakim Andersson <joakim.andersson@nordicsemi.no>
This commit is contained in:
Joakim Andersson 2020-05-12 12:08:13 +02:00 committed by Carles Cufí
commit 1d0b03bb37
5 changed files with 52 additions and 13 deletions

View file

@ -81,10 +81,23 @@ struct bt_conn_le_phy_info {
uint8_t rx_phy; /** Connection receive PHY */
};
/** Connection PHY options */
enum {
/** Convenience value when no options are specified. */
BT_CONN_LE_PHY_OPT_NONE = 0,
/** LE Coded using S=2 coding preferred when transmitting. */
BT_CONN_LE_PHY_OPT_CODED_S2 = BIT(0),
/** LE Coded using S=8 coding preferred when transmitting. */
BT_CONN_LE_PHY_OPT_CODED_S8 = BIT(1),
};
/** Preferred PHY parameters for LE connections */
struct bt_conn_le_phy_param {
uint8_t pref_tx_phy; /** Bitmask of preferred transmit PHYs */
uint8_t pref_rx_phy; /** Bitmask of preferred receive PHYs */
uint16_t options; /** Connection PHY options. */
uint8_t pref_tx_phy; /** Bitmask of preferred transmit PHYs */
uint8_t pref_rx_phy; /** Bitmask of preferred receive PHYs */
};
/** Initialize PHY parameters
@ -94,6 +107,7 @@ struct bt_conn_le_phy_param {
*/
#define BT_CONN_LE_PHY_PARAM_INIT(_pref_tx_phy, _pref_rx_phy) \
{ \
.option = BT_CONN_LE_PHY_OPT_NONE, \
.pref_tx_phy = (_pref_tx_phy), \
.pref_rx_phy = (_pref_rx_phy), \
}
@ -398,6 +412,9 @@ int bt_conn_le_data_len_update(struct bt_conn *conn,
const struct bt_conn_le_data_len_param *param);
/** @brief Update the connection PHY parameters.
*
* Update the preferred transmit and receive PHYs of the connection.
* Use @ref BT_GAP_LE_PHY_NONE to indicate no preference.
*
* @param conn Connection object.
* @param param Updated connection parameters.

View file

@ -78,6 +78,8 @@ extern "C" {
/** LE PHY types */
enum {
/** Convenience macro for when no PHY is set. */
BT_GAP_LE_PHY_NONE = 0,
/** LE 1M PHY */
BT_GAP_LE_PHY_1M = BIT(0),
/** LE 2M PHY */

View file

@ -2118,17 +2118,35 @@ int bt_conn_le_data_len_update(struct bt_conn *conn,
int bt_conn_le_phy_update(struct bt_conn *conn,
const struct bt_conn_le_phy_param *param)
{
if (conn->le.phy.tx_phy == param->pref_tx_phy &&
conn->le.phy.rx_phy == param->pref_rx_phy) {
return -EALREADY;
}
uint8_t phy_opts, all_phys;
if (IS_ENABLED(CONFIG_BT_AUTO_PHY_UPDATE) &&
!atomic_test_bit(conn->flags, BT_CONN_AUTO_PHY_COMPLETE)) {
return -EAGAIN;
}
return bt_le_set_phy(conn, param->pref_tx_phy, param->pref_rx_phy);
if ((param->options & BT_CONN_LE_PHY_OPT_CODED_S2) &&
(param->options & BT_CONN_LE_PHY_OPT_CODED_S8)) {
phy_opts = BT_HCI_LE_PHY_CODED_ANY;
} else if (param->options & BT_CONN_LE_PHY_OPT_CODED_S2) {
phy_opts = BT_HCI_LE_PHY_CODED_S2;
} else if (param->options & BT_CONN_LE_PHY_OPT_CODED_S8) {
phy_opts = BT_HCI_LE_PHY_CODED_S8;
} else {
phy_opts = BT_HCI_LE_PHY_CODED_ANY;
}
all_phys = 0U;
if (param->pref_tx_phy == BT_GAP_LE_PHY_NONE) {
all_phys |= BT_HCI_LE_PHY_TX_ANY;
}
if (param->pref_rx_phy == BT_GAP_LE_PHY_NONE) {
all_phys |= BT_HCI_LE_PHY_RX_ANY;
}
return bt_le_set_phy(conn, all_phys, param->pref_tx_phy,
param->pref_rx_phy, phy_opts);
}
#endif

View file

@ -1788,7 +1788,8 @@ static int hci_le_read_phy(struct bt_conn *conn)
}
#endif /* defined(CONFIG_BT_USER_PHY_UPDATE) */
int bt_le_set_phy(struct bt_conn *conn, uint8_t pref_tx_phy, uint8_t pref_rx_phy)
int bt_le_set_phy(struct bt_conn *conn, uint8_t all_phys,
uint8_t pref_tx_phy, uint8_t pref_rx_phy, uint8_t phy_opts)
{
struct bt_hci_cp_le_set_phy *cp;
struct net_buf *buf;
@ -1800,10 +1801,10 @@ int bt_le_set_phy(struct bt_conn *conn, uint8_t pref_tx_phy, uint8_t pref_rx_phy
cp = net_buf_add(buf, sizeof(*cp));
cp->handle = sys_cpu_to_le16(conn->handle);
cp->all_phys = 0U;
cp->all_phys = all_phys;
cp->tx_phys = pref_tx_phy;
cp->rx_phys = pref_rx_phy;
cp->phy_opts = BT_HCI_LE_PHY_CODED_ANY;
cp->phy_opts = phy_opts;
return bt_hci_cmd_send(BT_HCI_OP_LE_SET_PHY, buf);
}
@ -1929,9 +1930,9 @@ static void conn_auto_initiate(struct bt_conn *conn)
if (IS_ENABLED(CONFIG_BT_AUTO_PHY_UPDATE) &&
!atomic_test_bit(conn->flags, BT_CONN_AUTO_PHY_COMPLETE) &&
BT_FEAT_LE_PHY_2M(bt_dev.le.features)) {
err = bt_le_set_phy(conn,
err = bt_le_set_phy(conn, 0U, BT_HCI_LE_PHY_PREFER_2M,
BT_HCI_LE_PHY_PREFER_2M,
BT_HCI_LE_PHY_PREFER_2M);
BT_HCI_LE_PHY_CODED_ANY);
if (!err) {
atomic_set_bit(conn->flags, BT_CONN_AUTO_PHY_UPDATE);
return;

View file

@ -255,7 +255,8 @@ int bt_hci_disconnect(uint16_t handle, uint8_t reason);
bool bt_le_conn_params_valid(const struct bt_le_conn_param *param);
int bt_le_set_data_len(struct bt_conn *conn, uint16_t tx_octets, uint16_t tx_time);
int bt_le_set_phy(struct bt_conn *conn, uint8_t tx_phy, uint8_t rx_phy);
int bt_le_set_phy(struct bt_conn *conn, uint8_t all_phys,
uint8_t pref_tx_phy, uint8_t pref_rx_phy, uint8_t phy_opts);
int bt_le_scan_update(bool fast_scan);