Re: [PATCH BlueZ v2 07/11] emulator: Add 5.0 feature support

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Jaganath,

On Tue, Apr 24, 2018 at 5:00 PM, Jaganath Kanakkassery
<jaganath.k.os@xxxxxxxxx> wrote:
> This adds new hciemu for BT 5.0. Also adds extended advertising,
> scanning and connection support in btdev and bthost
> ---
>  emulator/btdev.c  | 458 ++++++++++++++++++++++++++++++++++++++++++++++++++++--
>  emulator/btdev.h  |   1 +
>  emulator/bthost.c |  99 ++++++++++++
>  emulator/bthost.h |   7 +
>  emulator/hciemu.c |   3 +
>  emulator/hciemu.h |   1 +
>  monitor/bt.h      |   1 +
>  7 files changed, 560 insertions(+), 10 deletions(-)
>
> diff --git a/emulator/btdev.c b/emulator/btdev.c
> index 69d84a5..c2859a6 100644
> --- a/emulator/btdev.c
> +++ b/emulator/btdev.c
> @@ -145,6 +145,8 @@ struct btdev {
>         uint16_t sync_train_interval;
>         uint32_t sync_train_timeout;
>         uint8_t  sync_train_service_data;
> +
> +       uint16_t le_ext_adv_type;
>  };
>
>  struct inquiry_data {
> @@ -469,6 +471,34 @@ static void set_bredrle_commands(struct btdev *btdev)
>         btdev->commands[32] |= 0x40;    /* Read Local OOB Extended Data */
>  }
>
> +static void set_bredrle50_commands(struct btdev *btdev)
> +{
> +       set_bredrle_commands(btdev);
> +
> +       btdev->commands[36] |= 0x02;    /* LE Set Advertising Set Random Address */
> +       btdev->commands[36] |= 0x04;    /* LE Set Extended Advertising Parameters */
> +       btdev->commands[36] |= 0x08;    /* LE Set Extended Advertising Data */
> +       btdev->commands[36] |= 0x10;    /* LE Set Extended Scan Response Data */
> +       btdev->commands[36] |= 0x20;    /* LE Set Extended Advertising Enable */
> +       btdev->commands[36] |= 0x40;    /* LE Read Maximum Advertising Data Length */
> +       btdev->commands[36] |= 0x80;    /* LE Read Number of Supported Advertising Sets */
> +       btdev->commands[37] |= 0x01;    /* LE Remove Advertising Set */
> +       btdev->commands[37] |= 0x02;    /* LE Clear Advertising Sets */
> +       btdev->commands[37] |= 0x04;    /* LE Set Periodic Advertising Parameters */
> +       btdev->commands[37] |= 0x08;    /* LE Set Periodic Advertising Data */
> +       btdev->commands[37] |= 0x10;    /* LE Set Periodic Advertising Enable */
> +       btdev->commands[37] |= 0x20;    /* LE Set Extended Scan Parameters */
> +       btdev->commands[37] |= 0x40;    /* LE Set Extended Scan Enable */
> +       btdev->commands[37] |= 0x80;    /* LE Extended Create Connection */
> +       btdev->commands[38] |= 0x01;    /* LE Periodic Advertising Create Sync */
> +       btdev->commands[38] |= 0x02;    /* LE Periodic Advertising Create Sync Cancel */
> +       btdev->commands[38] |= 0x04;    /* LE Periodic Advertising Terminate Sync */
> +       btdev->commands[38] |= 0x08;    /* LE Add Device To Periodic Advertiser List */
> +       btdev->commands[38] |= 0x10;    /* LE Remove Device From Periodic Advertiser List */
> +       btdev->commands[38] |= 0x20;    /* LE Clear Periodic Advertiser List */
> +       btdev->commands[38] |= 0x40;    /* LE Read Periodic Advertiser List Size */
> +}
> +
>  static void set_amp_commands(struct btdev *btdev)
>  {
>         set_common_commands_all(btdev);
> @@ -570,6 +600,15 @@ static void set_le_features(struct btdev *btdev)
>         btdev->le_features[0] |= 0x08;  /* Slave-initiated Features Exchange */
>  }
>
> +static void set_bredrle50_features(struct btdev *btdev)
> +{
> +       set_bredrle_features(btdev);
> +
> +       btdev->le_features[1] |= 0x01;  /* LE 2M PHY */
> +       btdev->le_features[1] |= 0x08;  /* LE Coded PHY */
> +       btdev->le_features[1] |= 0x10;  /* LE EXT ADV */

I wouldn't add a different type for these features, at least not 2M
and EXT Adv which Id expect to be common.

> +}
> +
>  static void set_le_states(struct btdev *btdev)
>  {
>         /* Set all 41 bits as per Bluetooth 5.0 specification */
> @@ -596,7 +635,8 @@ struct btdev *btdev_create(enum btdev_type type, uint16_t id)
>
>         memset(btdev, 0, sizeof(*btdev));
>
> -       if (type == BTDEV_TYPE_BREDRLE || type == BTDEV_TYPE_LE) {
> +       if (type == BTDEV_TYPE_BREDRLE || type == BTDEV_TYPE_LE
> +                               || BTDEV_TYPE_BREDRLE50) {
>                 btdev->crypto = bt_crypto_new();
>                 if (!btdev->crypto) {
>                         free(btdev);
> @@ -637,6 +677,12 @@ struct btdev *btdev_create(enum btdev_type type, uint16_t id)
>                 set_bredr20_features(btdev);
>                 set_bredr20_commands(btdev);
>                 break;
> +       case BTDEV_TYPE_BREDRLE50:
> +               btdev->version = 0x05;
> +               set_bredrle50_features(btdev);
> +               set_bredrle50_commands(btdev);
> +               set_le_states(btdev);
> +               break;
>         }
>
>         btdev->page_scan_interval = 0x0800;
> @@ -1174,6 +1220,53 @@ static void le_conn_complete(struct btdev *btdev,
>         send_event(btdev, BT_HCI_EVT_LE_META_EVENT, buf, sizeof(buf));
>  }
>
> +static void le_ext_conn_complete(struct btdev *btdev,
> +                               const struct bt_hci_cmd_le_ext_create_conn *leecc,
> +                               uint8_t status)
> +{
> +       char buf[1 + sizeof(struct bt_hci_evt_le_enhanced_conn_complete)];
> +       struct bt_hci_evt_le_enhanced_conn_complete *cc = (void *) &buf[1];
> +       struct bt_hci_le_ext_create_conn *lecc = (void *)leecc->data;
> +
> +       memset(buf, 0, sizeof(buf));
> +
> +       buf[0] = BT_HCI_EVT_LE_ENHANCED_CONN_COMPLETE;
> +
> +       if (!status) {
> +               struct btdev *remote;
> +
> +               remote = find_btdev_by_bdaddr_type(leecc->peer_addr,
> +                                                       leecc->peer_addr_type);
> +
> +               btdev->conn = remote;
> +               btdev->le_adv_enable = 0;
> +               remote->conn = btdev;
> +               remote->le_adv_enable = 0;
> +
> +               cc->status = status;
> +               cc->peer_addr_type = btdev->le_scan_own_addr_type;
> +               if (cc->peer_addr_type == 0x01)
> +                       memcpy(cc->peer_addr, btdev->random_addr, 6);
> +               else
> +                       memcpy(cc->peer_addr, btdev->bdaddr, 6);
> +
> +               cc->role = 0x01;
> +               cc->handle = cpu_to_le16(42);
> +               cc->interval = lecc->max_interval;
> +               cc->latency = lecc->latency;
> +               cc->supv_timeout = lecc->supv_timeout;
> +
> +               send_event(remote, BT_HCI_EVT_LE_META_EVENT, buf, sizeof(buf));
> +       }
> +
> +       cc->status = status;
> +       cc->peer_addr_type = leecc->peer_addr_type;
> +       memcpy(cc->peer_addr, leecc->peer_addr, 6);
> +       cc->role = 0x00;
> +
> +       send_event(btdev, BT_HCI_EVT_LE_META_EVENT, buf, sizeof(buf));
> +}
> +
>  static const uint8_t *scan_addr(const struct btdev *btdev)
>  {
>         if (btdev->le_scan_own_addr_type == 0x01)
> @@ -1202,6 +1295,18 @@ static bool adv_match(struct btdev *scan, struct btdev *adv)
>         return !memcmp(scan_addr(scan), adv->le_adv_direct_addr, 6);
>  }
>
> +static bool ext_adv_match(struct btdev *scan, struct btdev *adv)
> +{
> +       /* Match everything if this is not directed advertising */
> +       if (!(adv->le_ext_adv_type & 0x04))
> +               return true;
> +
> +       if (scan->le_scan_own_addr_type != adv->le_adv_direct_addr_type)
> +               return false;
> +
> +       return !memcmp(scan_addr(scan), adv->le_adv_direct_addr, 6);
> +}
> +
>  static bool adv_connectable(struct btdev *btdev)
>  {
>         if (!btdev->le_adv_enable)
> @@ -1210,6 +1315,14 @@ static bool adv_connectable(struct btdev *btdev)
>         return btdev->le_adv_type != 0x03;
>  }
>
> +static bool ext_adv_connectable(struct btdev *btdev)
> +{
> +       if (!btdev->le_adv_enable)
> +               return false;
> +
> +       return btdev->le_ext_adv_type & 0x01;
> +}
> +
>  static void le_conn_request(struct btdev *btdev,
>                                 const struct bt_hci_cmd_le_create_conn *lecc)
>  {
> @@ -1224,6 +1337,20 @@ static void le_conn_request(struct btdev *btdev,
>                                         BT_HCI_ERR_CONN_FAILED_TO_ESTABLISH);
>  }
>
> +static void le_ext_conn_request(struct btdev *btdev,
> +                               const struct bt_hci_cmd_le_ext_create_conn *leecc)
> +{
> +       struct btdev *remote = find_btdev_by_bdaddr_type(leecc->peer_addr,
> +                                                       leecc->peer_addr_type);
> +
> +       if (remote && ext_adv_connectable(remote) && ext_adv_match(btdev, remote) &&
> +                               remote->le_adv_own_addr == leecc->peer_addr_type)
> +               le_ext_conn_complete(btdev, leecc, 0);
> +       else
> +               le_ext_conn_complete(btdev, leecc,
> +                                       BT_HCI_ERR_CONN_FAILED_TO_ESTABLISH);
> +}
> +
>  static void conn_request(struct btdev *btdev, const uint8_t *bdaddr)
>  {
>         struct btdev *remote = find_btdev_by_bdaddr(bdaddr);
> @@ -1851,6 +1978,47 @@ static void le_send_adv_report(struct btdev *btdev, const struct btdev *remote,
>                                         1 + 10 + meta_event.lar.data_len + 1);
>  }
>
> +static void le_send_ext_adv_report(struct btdev *btdev,
> +                                       const struct btdev *remote,
> +                                       uint16_t type, bool is_scan_rsp)
> +{
> +       struct __packed {
> +               uint8_t subevent;
> +               uint8_t num_reports;
> +               union {
> +                       struct bt_hci_le_ext_adv_report lear;
> +                       uint8_t raw[24 + 31];
> +               };
> +       } meta_event;
> +
> +       meta_event.subevent = BT_HCI_EVT_LE_EXT_ADV_REPORT;
> +
> +       memset(&meta_event.lear, 0, sizeof(meta_event.lear));
> +       meta_event.num_reports = 1;
> +       meta_event.lear.event_type = cpu_to_le16(type);
> +       meta_event.lear.addr_type = remote->le_adv_own_addr;
> +       memcpy(meta_event.lear.addr, adv_addr(remote), 6);
> +       meta_event.lear.rssi = 127;
> +       meta_event.lear.tx_power = 127;
> +       /* Right now we dont care about phy in adv report */
> +       meta_event.lear.primary_phy = 0x01;
> +       meta_event.lear.secondary_phy = 0x01;
> +
> +       /* Scan or advertising response */
> +       if (is_scan_rsp) {
> +               meta_event.lear.data_len = remote->le_scan_data_len;
> +               memcpy(meta_event.lear.data, remote->le_scan_data,
> +                                               meta_event.lear.data_len);
> +       } else {
> +               meta_event.lear.data_len = remote->le_adv_data_len;
> +               memcpy(meta_event.lear.data, remote->le_adv_data,
> +                                               meta_event.lear.data_len);
> +       }
> +
> +       send_event(btdev, BT_HCI_EVT_LE_META_EVENT, &meta_event,
> +                                       1 + 1 + 24 + meta_event.lear.data_len);
> +}
> +
>  static uint8_t get_adv_report_type(uint8_t adv_type)
>  {
>         /*
> @@ -1863,6 +2031,22 @@ static uint8_t get_adv_report_type(uint8_t adv_type)
>         return adv_type;
>  }
>
> +static uint8_t get_ext_adv_report_type(uint8_t ext_adv_type)
> +{
> +       /* If legacy bit is not set then just reset high duty cycle directed bit */
> +       if (!(ext_adv_type & 0x10))
> +               return (ext_adv_type & 0xf7);
> +
> +       /*
> +        * Connectable low duty cycle directed advertising creates a
> +        * connectable directed advertising report type.
> +        */
> +       if (ext_adv_type == 0x001d)
> +               return 0x0015;
> +
> +       return ext_adv_type;
> +}
> +
>  static void le_set_adv_enable_complete(struct btdev *btdev)
>  {
>         uint8_t report_type;
> @@ -1891,6 +2075,44 @@ static void le_set_adv_enable_complete(struct btdev *btdev)
>         }
>  }
>
> +static void le_set_ext_adv_enable_complete(struct btdev *btdev)
> +{
> +       uint16_t report_type;
> +       int i;
> +
> +       report_type = get_ext_adv_report_type(btdev->le_ext_adv_type);
> +
> +       for (i = 0; i < MAX_BTDEV_ENTRIES; i++) {
> +               if (!btdev_list[i] || btdev_list[i] == btdev)
> +                       continue;
> +
> +               if (!btdev_list[i]->le_scan_enable)
> +                       continue;
> +
> +               if (!ext_adv_match(btdev_list[i], btdev))
> +                       continue;
> +
> +               le_send_ext_adv_report(btdev_list[i], btdev, report_type, false);
> +
> +               if (btdev_list[i]->le_scan_type != 0x01)
> +                       continue;
> +
> +               /* if scannable bit is set the send scan response */
> +               if (btdev->le_ext_adv_type & 0x02) {
> +                       if (btdev->le_ext_adv_type == 0x13)
> +                               report_type = 0x1b;
> +                       else if (btdev->le_ext_adv_type == 0x12)
> +                               report_type = 0x1a;
> +                       else if (!(btdev->le_ext_adv_type & 0x10))
> +                               report_type &= 0x08;
> +                       else
> +                               continue;
> +
> +                       le_send_ext_adv_report(btdev_list[i], btdev, report_type, true);
> +               }
> +       }
> +}
> +
>  static void le_set_scan_enable_complete(struct btdev *btdev)
>  {
>         int i;
> @@ -1920,6 +2142,44 @@ static void le_set_scan_enable_complete(struct btdev *btdev)
>         }
>  }
>
> +static void le_set_ext_scan_enable_complete(struct btdev *btdev)
> +{
> +       int i;
> +
> +       for (i = 0; i < MAX_BTDEV_ENTRIES; i++) {
> +               uint16_t report_type;
> +
> +               if (!btdev_list[i] || btdev_list[i] == btdev)
> +                       continue;
> +
> +               if (!btdev_list[i]->le_adv_enable)
> +                       continue;
> +
> +               if (!ext_adv_match(btdev, btdev_list[i]))
> +                       continue;
> +
> +               report_type = get_ext_adv_report_type(btdev_list[i]->le_ext_adv_type);
> +               le_send_ext_adv_report(btdev, btdev_list[i], report_type, false);
> +
> +               if (btdev->le_scan_type != 0x01)
> +                       continue;
> +
> +                               /* if scannable bit is set the send scan response */
> +               if (btdev_list[i]->le_ext_adv_type & 0x02) {
> +                       if (btdev_list[i]->le_ext_adv_type == 0x13)
> +                               report_type = 0x1b;
> +                       else if (btdev_list[i]->le_ext_adv_type == 0x12)
> +                               report_type = 0x1a;
> +                       else if (!(btdev_list[i]->le_ext_adv_type & 0x10))
> +                               report_type &= 0x08;
> +                       else
> +                               continue;
> +
> +                       le_send_ext_adv_report(btdev, btdev_list[i], report_type, true);
> +               }
> +       }
> +}
> +
>  static void le_read_remote_features_complete(struct btdev *btdev)
>  {
>         char buf[1 + sizeof(struct bt_hci_evt_le_remote_features_complete)];
> @@ -2086,6 +2346,15 @@ static void default_cmd(struct btdev *btdev, uint16_t opcode,
>         const struct bt_hci_cmd_read_local_amp_assoc *rlaa_cmd;
>         const struct bt_hci_cmd_read_rssi *rrssi;
>         const struct bt_hci_cmd_read_tx_power *rtxp;
> +       const struct bt_hci_cmd_le_set_adv_set_rand_addr *lsasra;
> +       const struct bt_hci_cmd_le_set_ext_adv_params *lseap;
> +       const struct bt_hci_cmd_le_set_ext_adv_enable *lseae;
> +       const struct bt_hci_cmd_le_set_ext_adv_data *lsead;
> +       const struct bt_hci_cmd_le_set_ext_scan_rsp_data *lsesrd;
> +       const struct bt_hci_cmd_le_set_default_phy *phys;
> +       const struct bt_hci_cmd_le_set_ext_scan_params *lsesp;
> +       const struct bt_hci_le_scan_phy *lsp;
> +       const struct bt_hci_cmd_le_set_ext_scan_enable *lsese;
>         struct bt_hci_rsp_read_default_link_policy rdlp;
>         struct bt_hci_rsp_read_stored_link_key rslk;
>         struct bt_hci_rsp_write_stored_link_key wslk;
> @@ -2145,6 +2414,8 @@ static void default_cmd(struct btdev *btdev, uint16_t opcode,
>         struct bt_hci_rsp_read_tx_power rtxp_rsp;
>         struct bt_hci_evt_le_read_local_pk256_complete pk_evt;
>         struct bt_hci_evt_le_generate_dhkey_complete dh_evt;
> +       struct bt_hci_rsp_le_read_num_supported_adv_sets rlrnsas;
> +       struct bt_hci_rsp_le_set_ext_adv_params rlseap;
>         uint8_t status, page;
>
>         switch (opcode) {
> @@ -2679,7 +2950,8 @@ static void default_cmd(struct btdev *btdev, uint16_t opcode,
>                 break;
>
>         case BT_HCI_CMD_READ_LE_HOST_SUPPORTED:
> -               if (btdev->type != BTDEV_TYPE_BREDRLE)
> +               if (btdev->type != BTDEV_TYPE_BREDRLE &&
> +                               btdev->type != BTDEV_TYPE_BREDRLE50)
>                         goto unsupported;
>                 rlhs.status = BT_HCI_ERR_SUCCESS;
>                 rlhs.supported = btdev->le_supported;
> @@ -2688,7 +2960,8 @@ static void default_cmd(struct btdev *btdev, uint16_t opcode,
>                 break;
>
>         case BT_HCI_CMD_WRITE_LE_HOST_SUPPORTED:
> -               if (btdev->type != BTDEV_TYPE_BREDRLE)
> +               if (btdev->type != BTDEV_TYPE_BREDRLE &&
> +                               btdev->type != BTDEV_TYPE_BREDRLE50)
>                         goto unsupported;
>                 wlhs = data;
>                 btdev->le_supported = wlhs->supported;
> @@ -2698,7 +2971,8 @@ static void default_cmd(struct btdev *btdev, uint16_t opcode,
>                 break;
>
>         case BT_HCI_CMD_READ_SECURE_CONN_SUPPORT:
> -               if (btdev->type != BTDEV_TYPE_BREDRLE)
> +               if (btdev->type != BTDEV_TYPE_BREDRLE &&
> +                               btdev->type != BTDEV_TYPE_BREDRLE50)
>                         goto unsupported;
>                 rscs.status = BT_HCI_ERR_SUCCESS;
>                 rscs.support = btdev->secure_conn_support;
> @@ -2706,7 +2980,8 @@ static void default_cmd(struct btdev *btdev, uint16_t opcode,
>                 break;
>
>         case BT_HCI_CMD_WRITE_SECURE_CONN_SUPPORT:
> -               if (btdev->type != BTDEV_TYPE_BREDRLE)
> +               if (btdev->type != BTDEV_TYPE_BREDRLE &&
> +                               btdev->type != BTDEV_TYPE_BREDRLE50)
>                         goto unsupported;
>                 wscs = data;
>                 btdev->secure_conn_support = wscs->support;
> @@ -2715,14 +2990,16 @@ static void default_cmd(struct btdev *btdev, uint16_t opcode,
>                 break;
>
>         case BT_HCI_CMD_READ_LOCAL_OOB_EXT_DATA:
> -               if (btdev->type != BTDEV_TYPE_BREDRLE)
> +               if (btdev->type != BTDEV_TYPE_BREDRLE &&
> +                               btdev->type != BTDEV_TYPE_BREDRLE50)
>                         goto unsupported;
>                 rloed.status = BT_HCI_ERR_SUCCESS;
>                 cmd_complete(btdev, opcode, &rloed, sizeof(rloed));
>                 break;
>
>         case BT_HCI_CMD_READ_SYNC_TRAIN_PARAMS:
> -               if (btdev->type != BTDEV_TYPE_BREDRLE)
> +               if (btdev->type != BTDEV_TYPE_BREDRLE &&
> +                               btdev->type != BTDEV_TYPE_BREDRLE50)
>                         goto unsupported;
>                 rstp.status = BT_HCI_ERR_SUCCESS;
>                 rstp.interval = cpu_to_le16(btdev->sync_train_interval);
> @@ -2872,7 +3149,8 @@ static void default_cmd(struct btdev *btdev, uint16_t opcode,
>
>         case BT_HCI_CMD_READ_ENCRYPT_KEY_SIZE:
>                 if (btdev->type != BTDEV_TYPE_BREDRLE &&
> -                                       btdev->type != BTDEV_TYPE_BREDR)
> +                                       btdev->type != BTDEV_TYPE_BREDR &&
> +                                       btdev->type != BTDEV_TYPE_BREDRLE50)
>                         goto unsupported;
>                 reks = data;
>                 read_enc_key_size_complete(btdev, le16_to_cpu(reks->handle));
> @@ -2918,7 +3196,8 @@ static void default_cmd(struct btdev *btdev, uint16_t opcode,
>                 break;
>
>         case BT_HCI_CMD_SET_EVENT_MASK_PAGE2:
> -               if (btdev->type != BTDEV_TYPE_BREDRLE)
> +               if (btdev->type != BTDEV_TYPE_BREDRLE &&
> +                               btdev->type != BTDEV_TYPE_BREDRLE50)
>                         goto unsupported;
>                 semp2 = data;
>                 memcpy(btdev->event_mask_page2, semp2->mask, 8);
> @@ -3245,6 +3524,149 @@ static void default_cmd(struct btdev *btdev, uint16_t opcode,
>                 lcprnr_rsp.status = BT_HCI_ERR_SUCCESS;
>                 cmd_complete(btdev, opcode, &lcprnr_rsp, sizeof(lcprnr_rsp));
>                 break;
> +       case BT_HCI_CMD_LE_READ_NUM_SUPPORTED_ADV_SETS:
> +               if (btdev->type != BTDEV_TYPE_BREDRLE50)
> +                       goto unsupported;
> +
> +               rlrnsas.status = BT_HCI_ERR_SUCCESS;
> +               /* Support one set as of now */
> +               rlrnsas.num_of_sets = 1;
> +               cmd_complete(btdev, opcode, &rlrnsas, sizeof(rlrnsas));
> +               break;
> +       case BT_HCI_CMD_LE_SET_ADV_SET_RAND_ADDR:
> +               if (btdev->type != BTDEV_TYPE_BREDRLE50)
> +                       goto unsupported;
> +
> +               lsasra = data;
> +               memcpy(btdev->random_addr, lsasra->bdaddr, 6);
> +               status = BT_HCI_ERR_SUCCESS;
> +               cmd_complete(btdev, opcode, &status, sizeof(status));
> +               break;
> +       case BT_HCI_CMD_LE_SET_EXT_ADV_PARAMS:
> +               if (btdev->type != BTDEV_TYPE_BREDRLE50)
> +                       goto unsupported;
> +
> +               if (btdev->le_adv_enable) {
> +                       status = BT_HCI_ERR_COMMAND_DISALLOWED;
> +                       cmd_complete(btdev, opcode, &status, sizeof(status));
> +                       break;
> +               }
> +
> +               lseap = data;
> +               btdev->le_ext_adv_type = le16_to_cpu(lseap->evt_properties);
> +               btdev->le_adv_own_addr = lseap->own_addr_type;
> +               btdev->le_adv_direct_addr_type = lseap->peer_addr_type;
> +               memcpy(btdev->le_adv_direct_addr, lseap->peer_addr, 6);
> +
> +               rlseap.status = BT_HCI_ERR_SUCCESS;
> +               rlseap.tx_power = 0;
> +               cmd_complete(btdev, opcode, &rlseap, sizeof(rlseap));
> +               break;
> +       case BT_HCI_CMD_LE_SET_EXT_ADV_ENABLE:
> +               if (btdev->type != BTDEV_TYPE_BREDRLE50)
> +                       goto unsupported;
> +
> +               lseae = data;
> +               if (btdev->le_adv_enable == lseae->enable)
> +                       status = BT_HCI_ERR_COMMAND_DISALLOWED;
> +               else {
> +                       btdev->le_adv_enable = lseae->enable;
> +                       status = BT_HCI_ERR_SUCCESS;
> +               }
> +               cmd_complete(btdev, opcode, &status, sizeof(status));
> +               if (status == BT_HCI_ERR_SUCCESS && btdev->le_adv_enable)
> +                       le_set_ext_adv_enable_complete(btdev);
> +               break;
> +       case BT_HCI_CMD_LE_SET_EXT_ADV_DATA:
> +               if (btdev->type != BTDEV_TYPE_BREDRLE50)
> +                       goto unsupported;
> +
> +               lsead = data;
> +               btdev->le_adv_data_len = lsead->data_len;
> +               memcpy(btdev->le_adv_data, lsead->data, 31);
> +               status = BT_HCI_ERR_SUCCESS;
> +               cmd_complete(btdev, opcode, &status, sizeof(status));
> +               break;
> +       case BT_HCI_CMD_LE_SET_EXT_SCAN_RSP_DATA:
> +               if (btdev->type != BTDEV_TYPE_BREDRLE50)
> +                       goto unsupported;
> +
> +               lsesrd = data;
> +               btdev->le_scan_data_len = lsesrd->data_len;
> +               memcpy(btdev->le_scan_data, lsesrd->data, 31);
> +               status = BT_HCI_ERR_SUCCESS;
> +               cmd_complete(btdev, opcode, &status, sizeof(status));
> +               break;
> +       case BT_HCI_CMD_LE_REMOVE_ADV_SET:
> +               if (btdev->type != BTDEV_TYPE_BREDRLE50)
> +                       goto unsupported;
> +
> +               status = BT_HCI_ERR_SUCCESS;
> +               cmd_complete(btdev, opcode, &status, sizeof(status));
> +               break;
> +       case BT_HCI_CMD_LE_CLEAR_ADV_SETS:
> +               if (btdev->type != BTDEV_TYPE_BREDRLE50)
> +                       goto unsupported;
> +
> +               status = BT_HCI_ERR_SUCCESS;
> +               cmd_complete(btdev, opcode, &status, sizeof(status));
> +               break;
> +       case BT_HCI_CMD_LE_SET_DEFAULT_PHY:
> +               if (btdev->type == BTDEV_TYPE_BREDR)
> +                       goto unsupported;
> +               phys = data;
> +               if (phys->all_phys > 0x03 ||
> +                       (!(phys->all_phys & 0x01) &&
> +                               (!phys->tx_phys || phys->tx_phys > 0x07)) ||
> +                       (!(phys->all_phys & 0x02) &&
> +                               (!phys->rx_phys || phys->rx_phys > 0x07)))
> +                       status = BT_HCI_ERR_INVALID_PARAMETERS;
> +               else
> +                       status = BT_HCI_ERR_SUCCESS;
> +               cmd_complete(btdev, opcode, &status, sizeof(status));
> +               break;
> +       case BT_HCI_CMD_LE_SET_EXT_SCAN_PARAMS:
> +               if (btdev->type != BTDEV_TYPE_BREDRLE50)
> +                       goto unsupported;
> +
> +               lsesp = data;
> +               lsp = (void *)lsesp->data;
> +
> +               if (btdev->le_scan_enable)
> +                       status = BT_HCI_ERR_COMMAND_DISALLOWED;
> +               else if (lsesp->num_phys == 0)
> +                       status = BT_HCI_ERR_INVALID_PARAMETERS;
> +               else {
> +                       status = BT_HCI_ERR_SUCCESS;
> +                       /* Currently we dont support multiple types in single command
> +                        * So just take the first one will do.
> +                        */
> +                       btdev->le_scan_type = lsp->type;
> +                       btdev->le_scan_own_addr_type = lsesp->own_addr_type;
> +               }
> +
> +               cmd_complete(btdev, opcode, &status, sizeof(status));
> +               break;
> +       case BT_HCI_CMD_LE_SET_EXT_SCAN_ENABLE:
> +               if (btdev->type != BTDEV_TYPE_BREDRLE50)
> +                       goto unsupported;
> +
> +               lsese = data;
> +               if (btdev->le_scan_enable == lsese->enable)
> +                       status = BT_HCI_ERR_COMMAND_DISALLOWED;
> +               else {
> +                       btdev->le_scan_enable = lsese->enable;
> +                       btdev->le_filter_dup = lsese->filter_dup;
> +                       status = BT_HCI_ERR_SUCCESS;
> +               }
> +               cmd_complete(btdev, opcode, &status, sizeof(status));
> +               break;
> +       case BT_HCI_CMD_LE_EXT_CREATE_CONN:
> +               if (btdev->type != BTDEV_TYPE_BREDRLE50)
> +                       goto unsupported;
> +
> +               cmd_status(btdev, BT_HCI_ERR_SUCCESS, opcode);
> +               break;
>         default:
>                 goto unsupported;
>         }
> @@ -3282,6 +3704,8 @@ static void default_cmd_completion(struct btdev *btdev, uint16_t opcode,
>         const struct bt_hci_cmd_le_conn_param_req_reply *lcprr;
>         const struct bt_hci_cmd_le_conn_param_req_neg_reply *lcprnr;
>         const struct bt_hci_cmd_le_set_scan_enable *lsse;
> +       const struct bt_hci_cmd_le_set_ext_scan_enable *lsese;
> +       const struct bt_hci_cmd_le_ext_create_conn *leecc;
>
>         switch (opcode) {
>         case BT_HCI_CMD_INQUIRY:
> @@ -3476,7 +3900,21 @@ static void default_cmd_completion(struct btdev *btdev, uint16_t opcode,
>                 lsse = data;
>                 if (btdev->le_scan_enable && lsse->enable)
>                         le_set_scan_enable_complete(btdev);
> -
> +               break;
> +       case BT_HCI_CMD_LE_SET_EXT_SCAN_ENABLE:
> +               if (btdev->type != BTDEV_TYPE_BREDRLE50)
> +                       return;
> +               lsese = data;
> +               if (btdev->le_scan_enable && lsese->enable)
> +                       le_set_ext_scan_enable_complete(btdev);
> +               break;
> +       case BT_HCI_CMD_LE_EXT_CREATE_CONN:
> +               if (btdev->type != BTDEV_TYPE_BREDRLE50)
> +                       return;
> +               leecc = data;
> +               btdev->le_scan_own_addr_type = leecc->own_addr_type;
> +               le_ext_conn_request(btdev, leecc);
> +               break;
>         }
>  }
>
> diff --git a/emulator/btdev.h b/emulator/btdev.h
> index ba06a10..362d1e7 100644
> --- a/emulator/btdev.h
> +++ b/emulator/btdev.h
> @@ -63,6 +63,7 @@ enum btdev_type {
>         BTDEV_TYPE_LE,
>         BTDEV_TYPE_AMP,
>         BTDEV_TYPE_BREDR20,
> +       BTDEV_TYPE_BREDRLE50,
>  };
>
>  enum btdev_hook_type {
> diff --git a/emulator/bthost.c b/emulator/bthost.c
> index 2bcdc31..d37957f 100644
> --- a/emulator/bthost.c
> +++ b/emulator/bthost.c
> @@ -839,6 +839,12 @@ static void evt_cmd_complete(struct bthost *bthost, const void *data,
>                 break;
>         case BT_HCI_CMD_LE_SET_ADV_DATA:
>                 break;
> +       case BT_HCI_CMD_LE_SET_EXT_ADV_PARAMS:
> +               break;
> +       case BT_HCI_CMD_LE_SET_EXT_ADV_DATA:
> +               break;
> +       case BT_HCI_CMD_LE_SET_EXT_ADV_ENABLE:
> +               break;
>         default:
>                 printf("Unhandled cmd_complete opcode 0x%04x\n", opcode);
>                 break;
> @@ -1161,6 +1167,26 @@ static void evt_le_conn_complete(struct bthost *bthost, const void *data,
>         init_conn(bthost, le16_to_cpu(ev->handle), ev->peer_addr, addr_type);
>  }
>
> +static void evt_le_ext_conn_complete(struct bthost *bthost, const void *data,
> +                                                               uint8_t len)
> +{
> +       const struct bt_hci_evt_le_enhanced_conn_complete *ev = data;
> +       uint8_t addr_type;
> +
> +       if (len < sizeof(*ev))
> +               return;
> +
> +       if (ev->status)
> +               return;
> +
> +       if (ev->peer_addr_type == 0x00)
> +               addr_type = BDADDR_LE_PUBLIC;
> +       else
> +               addr_type = BDADDR_LE_RANDOM;
> +
> +       init_conn(bthost, le16_to_cpu(ev->handle), ev->peer_addr, addr_type);
> +}
> +
>  static void evt_le_conn_update_complete(struct bthost *bthost, const void *data,
>                                                                 uint8_t len)
>  {
> @@ -1240,6 +1266,9 @@ static void evt_le_meta_event(struct bthost *bthost, const void *data,
>         case BT_HCI_EVT_LE_LONG_TERM_KEY_REQUEST:
>                 evt_le_ltk_request(bthost, evt_data, len - 1);
>                 break;
> +       case BT_HCI_EVT_LE_ENHANCED_CONN_COMPLETE:
> +               evt_le_ext_conn_complete(bthost, evt_data, len - 1);
> +               break;
>         default:
>                 printf("Unsupported LE Meta event 0x%2.2x\n", *event);
>                 break;
> @@ -2269,6 +2298,38 @@ void bthost_hci_connect(struct bthost *bthost, const uint8_t *bdaddr,
>         }
>  }
>
> +void bthost_hci_ext_connect(struct bthost *bthost, const uint8_t *bdaddr,
> +                                                       uint8_t addr_type)
> +{
> +       struct bt_hci_cmd_le_ext_create_conn *cc;
> +       struct bt_hci_le_ext_create_conn *cp;
> +       uint8_t buf[sizeof(*cc) + sizeof(*cp)];
> +
> +       cc = (void *)buf;
> +       cp = (void *)cc->data;
> +
> +       bthost->conn_init = true;
> +
> +       memset(cc, 0, sizeof(*cc));
> +       memset(cp, 0, sizeof(*cp));
> +
> +       memcpy(cc->peer_addr, bdaddr, sizeof(cc->peer_addr));
> +
> +       if (addr_type == BDADDR_LE_RANDOM)
> +               cc->peer_addr_type = 0x01;
> +
> +       cc->phys = 0x01;
> +
> +       cp->scan_interval = cpu_to_le16(0x0060);
> +       cp->scan_window = cpu_to_le16(0x0030);
> +       cp->min_interval = cpu_to_le16(0x0028);
> +       cp->max_interval = cpu_to_le16(0x0038);
> +       cp->supv_timeout = cpu_to_le16(0x002a);
> +
> +       send_command(bthost, BT_HCI_CMD_LE_EXT_CREATE_CONN,
> +                                               buf, sizeof(buf));
> +}
> +
>  void bthost_hci_disconnect(struct bthost *bthost, uint16_t handle,
>                                                                 uint8_t reason)
>  {
> @@ -2301,6 +2362,29 @@ void bthost_set_adv_data(struct bthost *bthost, const uint8_t *data,
>                                                         sizeof(adv_cp));
>  }
>
> +void bthost_set_ext_adv_data(struct bthost *bthost, const uint8_t *data,
> +                                                               uint8_t len)
> +{
> +       struct bt_hci_cmd_le_set_ext_adv_data *adv_cp;
> +       uint8_t buf[sizeof(*adv_cp) + 31];
> +
> +       adv_cp = (void *)buf;
> +
> +       memset(adv_cp, 0, sizeof(*adv_cp));
> +       memset(adv_cp->data, 0, 31);
> +
> +       adv_cp->operation = 0x03;
> +       adv_cp->fragment_preference = 0x01;
> +
> +       if (len) {
> +               adv_cp->data_len = len;
> +               memcpy(adv_cp->data, data, len);
> +       }
> +
> +       send_command(bthost, BT_HCI_CMD_LE_SET_EXT_ADV_DATA, buf,
> +                                                       sizeof(buf));
> +}
> +
>  void bthost_set_adv_enable(struct bthost *bthost, uint8_t enable)
>  {
>         struct bt_hci_cmd_le_set_adv_parameters cp;
> @@ -2312,6 +2396,21 @@ void bthost_set_adv_enable(struct bthost *bthost, uint8_t enable)
>         send_command(bthost, BT_HCI_CMD_LE_SET_ADV_ENABLE, &enable, 1);
>  }
>
> +void bthost_set_ext_adv_enable(struct bthost *bthost, uint8_t enable)
> +{
> +       struct bt_hci_cmd_le_set_ext_adv_params cp;
> +       struct bt_hci_cmd_le_set_ext_adv_enable cp_enable;
> +
> +       memset(&cp, 0, sizeof(cp));
> +       cp.evt_properties = cpu_to_le16(0x0013);
> +       send_command(bthost, BT_HCI_CMD_LE_SET_EXT_ADV_PARAMS,
> +                                                       &cp, sizeof(cp));
> +
> +       cp_enable.enable = enable;
> +       send_command(bthost, BT_HCI_CMD_LE_SET_EXT_ADV_ENABLE, &cp_enable,
> +                                       sizeof(cp_enable));
> +}
> +
>  void bthost_write_ssp_mode(struct bthost *bthost, uint8_t mode)
>  {
>         send_command(bthost, BT_HCI_CMD_WRITE_SIMPLE_PAIRING_MODE, &mode, 1);
> diff --git a/emulator/bthost.h b/emulator/bthost.h
> index 553865a..b5f3696 100644
> --- a/emulator/bthost.h
> +++ b/emulator/bthost.h
> @@ -56,6 +56,9 @@ void bthost_set_connect_cb(struct bthost *bthost, bthost_new_conn_cb cb,
>  void bthost_hci_connect(struct bthost *bthost, const uint8_t *bdaddr,
>                                                         uint8_t addr_type);
>
> +void bthost_hci_ext_connect(struct bthost *bthost, const uint8_t *bdaddr,
> +                                                       uint8_t addr_type);
> +
>  void bthost_hci_disconnect(struct bthost *bthost, uint16_t handle,
>                                                                 uint8_t reason);
>
> @@ -83,6 +86,10 @@ void bthost_set_adv_data(struct bthost *bthost, const uint8_t *data,
>                                                                 uint8_t len);
>  void bthost_set_adv_enable(struct bthost *bthost, uint8_t enable);
>
> +void bthost_set_ext_adv_data(struct bthost *bthost, const uint8_t *data,
> +                                                               uint8_t len);
> +void bthost_set_ext_adv_enable(struct bthost *bthost, uint8_t enable);
> +
>  void bthost_write_ssp_mode(struct bthost *bthost, uint8_t mode);
>
>  void bthost_write_le_host_supported(struct bthost *bthost, uint8_t mode);
> diff --git a/emulator/hciemu.c b/emulator/hciemu.c
> index 1787a6c..bc36773 100644
> --- a/emulator/hciemu.c
> +++ b/emulator/hciemu.c
> @@ -331,6 +331,9 @@ struct hciemu *hciemu_new(enum hciemu_type type)
>         case HCIEMU_TYPE_LEGACY:
>                 hciemu->btdev_type = BTDEV_TYPE_BREDR20;
>                 break;
> +       case HCIEMU_TYPE_BREDRLE50:
> +               hciemu->btdev_type = BTDEV_TYPE_BREDRLE50;
> +               break;
>         default:
>                 return NULL;
>         }
> diff --git a/emulator/hciemu.h b/emulator/hciemu.h
> index 5c0c4c3..e37c069 100644
> --- a/emulator/hciemu.h
> +++ b/emulator/hciemu.h
> @@ -31,6 +31,7 @@ enum hciemu_type {
>         HCIEMU_TYPE_BREDR,
>         HCIEMU_TYPE_LE,
>         HCIEMU_TYPE_LEGACY,
> +       HCIEMU_TYPE_BREDRLE50,
>  };
>
>  enum hciemu_hook_type {
> diff --git a/monitor/bt.h b/monitor/bt.h
> index 595b6a7..ec62864 100644
> --- a/monitor/bt.h
> +++ b/monitor/bt.h
> @@ -3010,6 +3010,7 @@ struct bt_hci_le_ext_adv_report {
>         uint8_t  direct_addr_type;
>         uint8_t  direct_addr[6];
>         uint8_t  data_len;
> +       uint8_t  data[0];
>  } __attribute__ ((packed));
>
>  #define BT_HCI_EVT_LE_ADV_SET_TERM             0x12
> --
> 2.7.4
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
> the body of a message to majordomo@xxxxxxxxxxxxxxx
> More majordomo info at  http://vger.kernel.org/majordomo-info.html



-- 
Luiz Augusto von Dentz
--
To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Bluez Devel]     [Linux Wireless Networking]     [Linux Wireless Personal Area Networking]     [Linux ATH6KL]     [Linux USB Devel]     [Linux Media Drivers]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Big List of Linux Books]

  Powered by Linux