/* Grab a reference if command needs to be associated with a sock (e.g. *likelymgmtsocketthatinitiatedthecommand).
*/ if (sk) {
hci_skb_sk(skb) = sk;
sock_hold(sk);
}
/* If an error occurred during request building, remove all HCI *commandsqueuedontheHCIrequestqueue.
*/ if (req->err) {
skb_queue_purge(&req->cmd_q); return req->err;
}
/* Do not allow empty requests */ if (skb_queue_empty(&req->cmd_q)) return -ENODATA;
if (!hci_dev_test_flag(hdev, HCI_LE_SCAN)) goto _return;
status = hci_cmd_sync_queue(hdev, scan_disable_sync, NULL, NULL); if (status) {
bt_dev_err(hdev, "failed to disable LE scan: %d", status); goto _return;
}
/* If we were running LE only scan, change discovery state. If *wewererunningbothLEandBR/EDRinquirysimultaneously, *andBR/EDRinquiryisalreadyfinished,stopdiscovery, *otherwiseBR/EDRinquirywillstopdiscoverywhenfinished. *Ifwewillresolveremotedevicename,donotchange *discoverystate.
*/
if (hdev->discovery.type == DISCOV_TYPE_LE) goto discov_stopped;
if (hdev->discovery.type != DISCOV_TYPE_INTERLEAVED) goto _return;
if (hci_test_quirk(hdev, HCI_QUIRK_SIMULTANEOUS_DISCOVERY)) { if (!test_bit(HCI_INQUIRY, &hdev->flags) &&
hdev->discovery.state != DISCOVERY_RESOLVING) goto discov_stopped;
goto _return;
}
status = hci_cmd_sync_queue(hdev, interleaved_inquiry_sync, NULL, NULL); if (status) {
bt_dev_err(hdev, "inquiry failed: status %d", status); goto discov_stopped;
}
/* For a single instance: *-force==true:Theinstancewillberemovedevenwhenitsremaining *lifetimeisnotzero. *-force==false:theinstancewillbedeactivatedbutkeptstoredunless *theremaininglifetimeiszero. * *Forinstance==0x00: *-force==true:Allinstanceswillberemovedregardlessoftheirtimeout *setting. *-force==false:Onlyinstancesthathaveatimeoutwillberemoved.
*/ int hci_clear_adv_instance_sync(struct hci_dev *hdev, struct sock *sk,
u8 instance, bool force)
{ struct adv_info *adv_instance, *n, *next_instance = NULL; int err;
u8 rem_inst;
/* Cancel any timeout concerning the removed instance(s). */ if (!instance || hdev->cur_adv_instance == instance)
cancel_adv_timeout(hdev);
/* Get the next instance to advertise BEFORE we remove *thecurrentone.Thiscanbethesameinstanceagain *ifthereisonlyoneinstance.
*/ if (instance && hdev->cur_adv_instance == instance)
next_instance = hci_get_next_instance(hdev, instance);
if (instance == 0x00) {
list_for_each_entry_safe(adv_instance, n, &hdev->adv_instances,
list) { if (!(force || adv_instance->timeout)) continue;
switch (hdev->interleave_scan_state) { case INTERLEAVE_SCAN_ALLOWLIST:
bt_dev_dbg(hdev, "next state: allowlist");
hdev->interleave_scan_state = INTERLEAVE_SCAN_NO_FILTER; break; case INTERLEAVE_SCAN_NO_FILTER:
bt_dev_dbg(hdev, "next state: no filter");
hdev->interleave_scan_state = INTERLEAVE_SCAN_ALLOWLIST; break; case INTERLEAVE_SCAN_NONE:
bt_dev_err(hdev, "unexpected error");
}
hci_dev_unlock(hdev);
/* Don't continue interleaving if it was canceled */ if (is_interleave_scanning(hdev))
queue_delayed_work(hdev->req_workqueue,
&hdev->interleave_scan, timeout);
}
if (hdev->req_status == HCI_REQ_PEND) { /* req_result is __u32 so error must be positive to be properly *propagated.
*/
hdev->req_result = err < 0 ? -err : err;
hdev->req_status = HCI_REQ_CANCELED;
/* Submit HCI command to be run in as cmd_sync_work: * *-hdevmust_not_beunregistered
*/ int hci_cmd_sync_submit(struct hci_dev *hdev, hci_cmd_sync_work_func_t func, void *data, hci_cmd_sync_work_destroy_t destroy)
{ struct hci_cmd_sync_work_entry *entry; int err = 0;
/* Queue HCI command: * *-hdevmustberunning
*/ int hci_cmd_sync_queue(struct hci_dev *hdev, hci_cmd_sync_work_func_t func, void *data, hci_cmd_sync_work_destroy_t destroy)
{ /* Only queue command if hdev is running which means it had been opened *andiseitheroninitphaseorisalreadyup.
*/ if (!test_bit(HCI_RUNNING, &hdev->flags)) return -ENETDOWN;
/* Run HCI command: * *-hdevmustberunning *-ifoncmd_sync_workthenrunimmediatelyotherwisequeue
*/ int hci_cmd_sync_run(struct hci_dev *hdev, hci_cmd_sync_work_func_t func, void *data, hci_cmd_sync_work_destroy_t destroy)
{ /* Only queue command if hdev is running which means it had been opened *andiseitheroninitphaseorisalreadyup.
*/ if (!test_bit(HCI_RUNNING, &hdev->flags)) return -ENETDOWN;
/* If on cmd_sync_work then run immediately otherwise queue */ if (current_work() == &hdev->cmd_sync_work) return func(hdev, data);
staticbool is_advertising_allowed(struct hci_dev *hdev, bool connectable)
{ /* If there is no connection we are OK to advertise. */ if (hci_conn_num(hdev, LE_LINK) == 0) returntrue;
/* Check le_states if there is any connection in peripheral role. */ if (hdev->conn_hash.le_num_peripheral > 0) { /* Peripheral connection state and non connectable mode *bit20.
*/ if (!connectable && !(hdev->le_states[2] & 0x10)) returnfalse;
/* Peripheral connection state and connectable mode bit 38 *andscannablebit21.
*/ if (connectable && (!(hdev->le_states[4] & 0x40) ||
!(hdev->le_states[2] & 0x20))) returnfalse;
}
/* Check le_states if there is any connection in central role. */ if (hci_conn_num(hdev, LE_LINK) != hdev->conn_hash.le_num_peripheral) { /* Central connection state and non connectable mode bit 18. */ if (!connectable && !(hdev->le_states[2] & 0x02)) returnfalse;
/* Central connection state and connectable mode bit 35 and *scannable19.
*/ if (connectable && (!(hdev->le_states[4] & 0x08) ||
!(hdev->le_states[2] & 0x08))) returnfalse;
}
returntrue;
}
staticbool adv_use_rpa(struct hci_dev *hdev, uint32_t flags)
{ /* If privacy is not enabled don't use RPA */ if (!hci_dev_test_flag(hdev, HCI_PRIVACY)) returnfalse;
/* If basic privacy mode is enabled use RPA */ if (!hci_dev_test_flag(hdev, HCI_LIMITED_PRIVACY)) returntrue;
/* If limited privacy mode is enabled don't use RPA if we're *bothdiscoverableandbondable.
*/ if ((flags & MGMT_ADV_FLAG_DISCOV) &&
hci_dev_test_flag(hdev, HCI_BONDABLE)) returnfalse;
/* We're neither bondable nor discoverable in the limited *privacymode,thereforeuseRPA.
*/ returntrue;
}
staticint hci_set_random_addr_sync(struct hci_dev *hdev, bdaddr_t *rpa)
{ /* If a random_addr has been set we're advertising or initiating an LE *connectionwecan'tgoaheadandchangetherandomaddressatthis *time.Thisisbecausetheeventualinitiatoraddressusedforthe *subsequentlycreatedconnectionwillbeundefined(some *controllersusethenewaddressandotherstheonewehad *whentheoperationstarted). * *Inthiskindofscenarioskiptheupdateandlettherandom *addressbeupdatedatthenextcycle.
*/ if (bacmp(&hdev->random_addr, BDADDR_ANY) &&
(hci_dev_test_flag(hdev, HCI_LE_ADV) ||
hci_lookup_le_connect(hdev))) {
bt_dev_dbg(hdev, "Deferring random address update");
hci_dev_set_flag(hdev, HCI_RPA_EXPIRED); return0;
}
int hci_update_random_address_sync(struct hci_dev *hdev, bool require_privacy, bool rpa, u8 *own_addr_type)
{ int err;
/* If privacy is enabled use a resolvable private address. If *currentRPAhasexpiredorthereissomethingelsethan *thecurrentRPAinuse,thengenerateanewone.
*/ if (rpa) { /* If Controller supports LL Privacy use own address type is *0x03
*/ if (ll_privacy_capable(hdev))
*own_addr_type = ADDR_LE_DEV_RANDOM_RESOLVED; else
*own_addr_type = ADDR_LE_DEV_RANDOM;
/* Check if RPA is valid */ if (rpa_valid(hdev)) return0;
err = smp_generate_rpa(hdev, hdev->irk, &hdev->rpa); if (err < 0) {
bt_dev_err(hdev, "failed to generate new RPA"); return err;
}
err = hci_set_random_addr_sync(hdev, &hdev->rpa); if (err) return err;
return0;
}
/* In case of required privacy without resolvable private address, *useannon-resolvableprivateaddress.Thisisusefulforactive *scanningandnon-connectableadvertising.
*/ if (require_privacy) {
bdaddr_t nrpa;
while (true) { /* The non-resolvable private address is generated *fromrandomsixbyteswiththetwomostsignificant *bitscleared.
*/
get_random_bytes(&nrpa, 6);
nrpa.b[5] &= 0x3f;
/* The non-resolvable private address shall not be *equaltothepublicaddress.
*/ if (bacmp(&hdev->bdaddr, &nrpa)) break;
}
*own_addr_type = ADDR_LE_DEV_RANDOM;
return hci_set_random_addr_sync(hdev, &nrpa);
}
/* If forcing static address is in use or there is no public *addressusethestaticaddressasrandomaddress(butskip *theHCIcommandifthecurrentrandomaddressisalreadythe *staticone. * *IncaseBR/EDRhasbeendisabledonadual-modecontroller *andastaticaddresshasbeenconfigured,thenusethat *addressinsteadofthepublicBR/EDRaddress.
*/ if (hci_dev_test_flag(hdev, HCI_FORCE_STATIC_ADDR) ||
!bacmp(&hdev->bdaddr, BDADDR_ANY) ||
(!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED) &&
bacmp(&hdev->static_addr, BDADDR_ANY))) {
*own_addr_type = ADDR_LE_DEV_RANDOM; if (bacmp(&hdev->static_addr, &hdev->random_addr)) return hci_set_random_addr_sync(hdev,
&hdev->static_addr); return0;
}
/* Neither privacy nor static address is being used so use a *publicaddress.
*/
*own_addr_type = ADDR_LE_DEV_PUBLIC;
/* If request specifies an instance that doesn't exist, fail */ if (instance > 0) {
adv = hci_find_adv_instance(hdev, instance); if (!adv) return -EINVAL;
/* If not enabled there is nothing to do */ if (!adv->enabled) return0;
}
memset(data, 0, sizeof(data));
cp = (void *)data;
set = (void *)cp->data;
/* Instance 0x00 indicates all advertising instances will be disabled */
cp->num_of_sets = !!instance;
cp->enable = 0x00;
if (instance > 0) {
adv = hci_find_adv_instance(hdev, instance); if (!adv) return -EINVAL;
} else {
adv = NULL;
}
/* Updating parameters of an active instance will return a *CommandDisallowederror,sowemustfirstdisablethe *instanceifitisactive.
*/ if (adv) {
err = hci_disable_ext_adv_instance_sync(hdev, instance); if (err) return err;
}
flags = hci_adv_instance_flags(hdev, instance);
/* If the "connectable" instance flag was not set, then choose between *ADV_INDandADV_NONCONN_INDbasedontheglobalconnectablesetting.
*/
connectable = (flags & MGMT_ADV_FLAG_CONNECTABLE) ||
mgmt_get_connectable(hdev);
if (!is_advertising_allowed(hdev, connectable)) return -EPERM;
/* Set require_privacy to true only when non-connectable *advertisingisusedanditisnotperiodic. *Inthatcaseitisfinetouseanon-resolvableprivateaddress.
*/
require_privacy = !connectable && !(adv && adv->periodic);
if (flags & MGMT_ADV_FLAG_SEC_2M) {
cp.primary_phy = HCI_ADV_PHY_1M;
cp.secondary_phy = HCI_ADV_PHY_2M;
} elseif (flags & MGMT_ADV_FLAG_SEC_CODED) {
cp.primary_phy = HCI_ADV_PHY_CODED;
cp.secondary_phy = HCI_ADV_PHY_CODED;
} else { /* In all other cases use 1M */
cp.primary_phy = HCI_ADV_PHY_1M;
cp.secondary_phy = HCI_ADV_PHY_1M;
}
err = hci_set_ext_adv_params_sync(hdev, adv, &cp, &rp); if (err) return err;
/* Update adv data as tx power is known now */
err = hci_set_ext_adv_data_sync(hdev, cp.handle); if (err) return err;
if ((own_addr_type == ADDR_LE_DEV_RANDOM ||
own_addr_type == ADDR_LE_DEV_RANDOM_RESOLVED) &&
bacmp(&random_addr, BDADDR_ANY)) { /* Check if random address need to be updated */ if (adv) { if (!bacmp(&random_addr, &adv->random_addr)) return0;
} else { if (!bacmp(&random_addr, &hdev->random_addr)) return0;
}
if (instance > 0) {
adv = hci_find_adv_instance(hdev, instance); if (!adv) return -EINVAL; /* If already enabled there is nothing to do */ if (adv->enabled) return0;
} else {
adv = NULL;
}
cp = (void *)data;
set = (void *)cp->data;
memset(cp, 0, sizeof(*cp));
cp->enable = 0x01;
cp->num_of_sets = 0x01;
memset(set, 0, sizeof(*set));
set->handle = adv ? adv->handle : instance;
/* Set duration per instance since controller is responsible for *schedulingit.
*/ if (adv && adv->timeout) {
u16 duration = adv->timeout * MSEC_PER_SEC;
/* Time = N * 10 ms */
set->duration = cpu_to_le16(duration / 10);
}
/* If periodic advertising already disabled there is nothing to do. */
adv = hci_find_adv_instance(hdev, instance); if (!adv || !adv->periodic_enabled) return0;
/* If periodic advertising already enabled there is nothing to do. */
adv = hci_find_adv_instance(hdev, instance); if (adv && adv->periodic_enabled) return0;
/* Checks if periodic advertising data contains a Basic Announcement and if it *doesgeneratesaBroadcastIDandaddBroadcastAnnouncement.
*/ staticint hci_adv_bcast_annoucement(struct hci_dev *hdev, struct adv_info *adv)
{
u8 bid[3];
u8 ad[HCI_MAX_EXT_AD_LENGTH];
u8 len;
/* Skip if NULL adv as instance 0x00 is used for general purpose *advertisingsoitcannotusedforthelikesofBroadcastAnnouncement *asitcanbeoverwrittenatanypoint.
*/ if (!adv) return0;
/* Check if PA data doesn't contains a Basic Audio Announcement then *thereisnothingtodo.
*/ if (!eir_get_service_data(adv->per_adv_data, adv->per_adv_data_len, 0x1851, NULL)) return0;
/* Check if advertising data already has a Broadcast Announcement since *theprocessmaywanttocontroltheBroadcastIDdirectlyandinthat *casethekernelshallnointerfere.
*/ if (eir_get_service_data(adv->adv_data, adv->adv_data_len, 0x1852,
NULL)) return0;
/* Generate Broadcast ID */
get_random_bytes(bid, sizeof(bid));
len = eir_append_service_data(ad, 0, 0x1852, bid, sizeof(bid));
memcpy(ad + len, adv->adv_data, adv->adv_data_len);
hci_set_adv_instance_data(hdev, adv->instance, len + adv->adv_data_len,
ad, 0, NULL);
if (instance) {
adv = hci_find_adv_instance(hdev, instance); if (adv) { if (sid != HCI_SID_INVALID && adv->sid != sid) { /* If the SID don't match attempt to find by *SID.
*/
adv = hci_find_adv_sid(hdev, sid); if (!adv) {
bt_dev_err(hdev, "Unable to find adv_info"); return -EINVAL;
}
}
/* Turn it into periodic advertising */
adv->periodic = true;
adv->per_adv_data_len = data_len; if (data)
memcpy(adv->per_adv_data, data, data_len);
adv->flags = flags;
} elseif (!adv) { /* Create an instance if that could not be found */
adv = hci_add_per_instance(hdev, instance, sid, flags,
data_len, data,
sync_interval,
sync_interval); if (IS_ERR(adv)) return PTR_ERR(adv);
adv->pending = false;
added = true;
}
}
/* If the "connectable" instance flag was not set, then choose between *ADV_INDandADV_NONCONN_INDbasedontheglobalconnectablesetting.
*/
connectable = (flags & MGMT_ADV_FLAG_CONNECTABLE) ||
mgmt_get_connectable(hdev);
if (!is_advertising_allowed(hdev, connectable)) return -EINVAL;
status = hci_disable_advertising_sync(hdev); if (status) return status;
/* Clear the HCI_LE_ADV bit temporarily so that the *hci_update_random_addressknowsthatit'ssafetogoahead *andwriteanewrandomaddress.Theflagwillbesetbackon *assoonastheSET_ADV_ENABLEHCIcommandcompletes.
*/
hci_dev_clear_flag(hdev, HCI_LE_ADV);
/* Set require_privacy to true only when non-connectable *advertisingisused.Inthatcaseitisfinetousea *non-resolvableprivateaddress.
*/
status = hci_update_random_address_sync(hdev, !connectable,
adv_use_rpa(hdev, flags),
&own_addr_type); if (status) return status;
if (hci_dev_test_flag(hdev, HCI_ADVERTISING) && !ext_adv_capable(hdev)) return -EPERM;
if (hdev->adv_instance_timeout) return -EBUSY;
adv = hci_find_adv_instance(hdev, instance); if (!adv) return -ENOENT;
/* A zero timeout means unlimited advertising. As long as there is *onlyoneinstance,durationshouldbeignored.Westillsetatimeout *incasefurtherinstancesarebeingaddedlateron. * *Iftheremaininglifetimeoftheinstanceismorethantheduration *thenthetimeoutcorrespondstotheduration,otherwiseitwillbe *reducedtotheremaininginstancelifetime.
*/ if (adv->timeout == 0 || adv->duration <= adv->remaining_time)
timeout = adv->duration; else
timeout = adv->remaining_time;
/* The remaining time is being reduced unless the instance is being *advertisedwithouttimelimit.
*/ if (adv->timeout)
adv->remaining_time = adv->remaining_time - timeout;
/* Only use work for scheduling instances with legacy advertising */ if (!ext_adv_capable(hdev)) {
hdev->adv_instance_timeout = timeout;
queue_delayed_work(hdev->req_workqueue,
&hdev->adv_instance_expire,
secs_to_jiffies(timeout));
}
/* If we're just re-scheduling the same instance again then do not *executeanyHCIcommands.Thishappenswhenasingleinstanceis *beingadvertised.
*/ if (!force && hdev->cur_adv_instance == instance &&
hci_dev_test_flag(hdev, HCI_LE_ADV)) return0;
hdev->cur_adv_instance = instance;
return hci_start_adv_sync(hdev, instance);
}
staticint hci_clear_adv_sets_sync(struct hci_dev *hdev, struct sock *sk)
{ int err;
if (!ext_adv_capable(hdev)) return0;
/* Disable instance 0x00 to disable all instances */
err = hci_disable_ext_adv_instance_sync(hdev, 0x00); if (err) return err;
/* If we use extended advertising, instance has to be removed first. */ if (ext_adv_capable(hdev)) return hci_remove_ext_adv_instance_sync(hdev, instance, sk);
/* This is safe as long as there is no command send while the lock is *held.
*/
hci_dev_lock(hdev);
err = hci_remove_adv_instance(hdev, instance); if (!err)
mgmt_advertising_removed(sk, hdev, instance);
hci_dev_unlock(hdev);
return err;
}
/* For a single instance: *-force==true:Theinstancewillberemovedevenwhenitsremaining *lifetimeisnotzero. *-force==false:theinstancewillbedeactivatedbutkeptstoredunless *theremaininglifetimeiszero. * *Forinstance==0x00: *-force==true:Allinstanceswillberemovedregardlessoftheirtimeout *setting. *-force==false:Onlyinstancesthathaveatimeoutwillberemoved.
*/ int hci_remove_advertising_sync(struct hci_dev *hdev, struct sock *sk,
u8 instance, bool force)
{ struct adv_info *next = NULL; int err;
/* Cancel any timeout concerning the removed instance(s). */ if (!instance || hdev->cur_adv_instance == instance)
cancel_adv_timeout(hdev);
/* Get the next instance to advertise BEFORE we remove *thecurrentone.Thiscanbethesameinstanceagain *ifthereisonlyoneinstance.
*/ if (hdev->cur_adv_instance == instance)
next = hci_get_next_instance(hdev, instance);
/* Return true if interleave_scan wasn't started until exiting this function, *otherwise,returnfalse
*/ staticbool hci_update_interleaved_scan_sync(struct hci_dev *hdev)
{ /* Do interleaved scan only if all of the following are true: *-ThereisatleastoneADVmonitor *-AtleastonependingLEconnectionoronedevicetobescannedfor *-Monitoroffloadingisnotsupported *Ifso,weshouldalternatebetweenallowlistscanandonewithout *anyfilterstosavepower.
*/ bool use_interleaving = hci_is_adv_monitoring(hdev) &&
!(list_empty(&hdev->pend_le_conns) &&
list_empty(&hdev->pend_le_reports)) &&
hci_get_adv_monitor_offload_ext(hdev) ==
HCI_ADV_MONITOR_EXT_NONE; bool is_interleaving = is_interleave_scanning(hdev);
/* Ignore errors when removing from resolving list as that is likely *thatthedevicewasneveradded.
*/
hci_le_del_resolve_list_sync(hdev, &cp.bdaddr, cp.bdaddr_type);
err = __hci_cmd_sync_status(hdev, HCI_OP_LE_DEL_FROM_ACCEPT_LIST, sizeof(cp), &cp, HCI_CMD_TIMEOUT); if (err) {
bt_dev_err(hdev, "Unable to remove from allow list: %d", err); return err;
}
bt_dev_dbg(hdev, "Remove %pMR (0x%x) from allow list", &cp.bdaddr,
cp.bdaddr_type);
irk = hci_find_irk_by_addr(hdev, ¶ms->addr, params->addr_type); if (!irk) return0;
/* Check if the IK has _not_ been programmed yet. */
entry = hci_bdaddr_list_lookup_with_irk(&hdev->le_resolv_list,
¶ms->addr,
params->addr_type); if (entry) return0;
rcu_read_lock();
p = hci_pend_le_action_lookup(&hdev->pend_le_conns,
¶ms->addr, params->addr_type); if (!p)
p = hci_pend_le_action_lookup(&hdev->pend_le_reports,
¶ms->addr, params->addr_type); if (p)
WRITE_ONCE(p->privacy_mode, HCI_NETWORK_PRIVACY);
rcu_read_unlock();
if (!ll_privacy_capable(hdev) ||
!(params->flags & HCI_CONN_FLAG_ADDRESS_RESOLUTION)) return0;
/* If device privacy mode has already been set there is nothing to do */ if (params->privacy_mode == HCI_DEVICE_PRIVACY) return0;
/* Check if HCI_CONN_FLAG_DEVICE_PRIVACY has been set as it also *indicatesthatLLPrivacyhasbeenenabledand *HCI_OP_LE_SET_PRIVACY_MODEissupported.
*/ if (!(params->flags & HCI_CONN_FLAG_DEVICE_PRIVACY)) return0;
irk = hci_find_irk_by_addr(hdev, ¶ms->addr, params->addr_type); if (!irk) return0;
/* Adds connection to allow list if needed, if the device uses RPA (has IRK) *thisattemptstoprogramthedeviceintheresolvinglistaswelland *properlysettheprivacymode.
*/ staticint hci_le_add_accept_list_sync(struct hci_dev *hdev, struct conn_params *params,
u8 *num_entries)
{ struct hci_cp_le_add_to_accept_list cp; int err;
/* During suspend, only wakeable devices can be in acceptlist */ if (hdev->suspended &&
!(params->flags & HCI_CONN_FLAG_REMOTE_WAKEUP)) {
hci_le_del_accept_list_sync(hdev, ¶ms->addr,
params->addr_type); return0;
}
/* Select filter policy to accept all advertising */ if (*num_entries >= hdev->le_accept_list_size) return -ENOSPC;
/* Attempt to program the device in the resolving list first to avoid *havingtorollbackincaseitfailssincetheresolvinglistis *dynamicitcanprobablybesmallerthantheacceptlist.
*/
err = hci_le_add_resolve_list_sync(hdev, params); if (err) {
bt_dev_err(hdev, "Unable to add to resolve list: %d", err); return err;
}
/* Set Privacy Mode */
err = hci_le_set_privacy_mode_sync(hdev, params); if (err) {
bt_dev_err(hdev, "Unable to set privacy mode: %d", err); return err;
}
/* Check if already in accept list */ if (hci_bdaddr_list_lookup(&hdev->le_accept_list, ¶ms->addr,
params->addr_type)) return0;
err = __hci_cmd_sync_status(hdev, HCI_OP_LE_ADD_TO_ACCEPT_LIST, sizeof(cp), &cp, HCI_CMD_TIMEOUT); if (err) {
bt_dev_err(hdev, "Unable to add to allow list: %d", err); /* Rollback the device from the resolving list */
hci_le_del_resolve_list_sync(hdev, &cp.bdaddr, cp.bdaddr_type); return err;
}
bt_dev_dbg(hdev, "Add %pMR (0x%x) to allow list", &cp.bdaddr,
cp.bdaddr_type);
return0;
}
/* This function disables/pause all advertising instances */ staticint hci_pause_advertising_sync(struct hci_dev *hdev)
{ int err; int old_state;
/* If controller is not advertising we are done. */ if (!hci_dev_test_flag(hdev, HCI_LE_ADV)) return0;
/* If already been paused there is nothing to do. */ if (hdev->advertising_paused) return0;
bt_dev_dbg(hdev, "Pausing directed advertising");
/* Stop directed advertising */
old_state = hci_dev_test_flag(hdev, HCI_ADVERTISING); if (old_state) { /* When discoverable timeout triggers, then just make sure *thelimiteddiscoverableflagiscleared.Eveninthecase *ofatimeouttriggeredfromgeneraldiscoverable,itis *safetounconditionallycleartheflag.
*/
hci_dev_clear_flag(hdev, HCI_LIMITED_DISCOVERABLE);
hci_dev_clear_flag(hdev, HCI_DISCOVERABLE);
hdev->discov_timeout = 0;
}
/* Call to disable any advertisements active on the controller. *Thiswillsucceedevenifnoadvertisementsareconfigured.
*/
err = hci_disable_advertising_sync(hdev); if (err) return err;
/* If we are using software rotation, pause the loop */ if (!ext_adv_capable(hdev))
cancel_adv_timeout(hdev);
/* This function enables all user advertising instances */ staticint hci_resume_advertising_sync(struct hci_dev *hdev)
{ struct adv_info *adv, *tmp; int err;
/* If advertising has not been paused there is nothing to do. */ if (!hdev->advertising_paused) return0;
if (ext_adv_capable(hdev)) { /* Call for each tracked instance to be re-enabled */
list_for_each_entry_safe(adv, tmp, &hdev->adv_instances, list) {
err = hci_enable_ext_advertising_sync(hdev,
adv->instance); if (!err) continue;
/* If the instance cannot be resumed remove it */
hci_remove_ext_adv_instance_sync(hdev, adv->instance,
NULL);
}
/* If current advertising instance is set to instance 0x00 *thenweneedtore-enableit.
*/ if (hci_dev_test_and_clear_flag(hdev, HCI_LE_ADV_0))
err = hci_enable_ext_advertising_sync(hdev, 0x00);
} else { /* Schedule for most recent instance to be restarted and begin *thesoftwarerotationloop
*/
err = hci_schedule_adv_instance_sync(hdev,
hdev->cur_adv_instance, true);
}
hdev->advertising_paused = false;
return err;
}
staticint hci_pause_addr_resolution(struct hci_dev *hdev)
{ int err;
if (!ll_privacy_capable(hdev)) return0;
if (!hci_dev_test_flag(hdev, HCI_LL_RPA_RESOLUTION)) return0;
/* Cannot disable addr resolution if scanning is enabled or *wheninitiatinganLEconnection.
*/ if (hci_dev_test_flag(hdev, HCI_LE_SCAN) ||
hci_lookup_le_connect(hdev)) {
bt_dev_err(hdev, "Command not allowed when scan/LE connect"); return -EPERM;
}
/* Cannot disable addr resolution if advertising is enabled. */
err = hci_pause_advertising_sync(hdev); if (err) {
bt_dev_err(hdev, "Pause advertising failed: %d", err); return err;
}
err = hci_le_set_addr_resolution_enable_sync(hdev, 0x00); if (err)
bt_dev_err(hdev, "Unable to disable Address Resolution: %d",
err);
/* Return if address resolution is disabled and RPA is not used. */ if (!err && scan_use_rpa(hdev)) return0;
/* Device must not be scanning when updating the accept list. * *Updateisdoneusingthefollowingsequence: * *ll_privacy_capable((DisableAdvertising)->DisableResolvingList)-> *RemoveDevicesFromAcceptList-> *(hasIRK&&ll_privacy_capable(RemoveDevicesFromResolvingList))-> *AddDevicestoAcceptList-> *(hasIRK&&ll_privacy_capable(RemoveDevicesFromResolvingList))-> *ll_privacy_capable(EnableResolvingList->(EnableAdvertising))-> *EnableScanning * *Incaseoffailureadvertisingshallberestoredtoitsoriginalstateand *returnwoulddisableacceptlistsinceeitheracceptorresolvinglistcould *notbeprogrammed. *
*/ static u8 hci_update_accept_list_sync(struct hci_dev *hdev)
{ struct conn_params *params; struct bdaddr_list *b, *t;
u8 num_entries = 0; bool pend_conn, pend_report;
u8 filter_policy;
size_t i, n; int err;
/* Pause advertising if resolving list can be used as controllers *cannotacceptresolvinglistmodificationswhileadvertising.
*/ if (ll_privacy_capable(hdev)) {
err = hci_pause_advertising_sync(hdev); if (err) {
bt_dev_err(hdev, "pause advertising failed: %d", err); return0x00;
}
}
/* Disable address resolution while reprogramming accept list since *devicesthatdohaveanIRKwillbeprogrammedintheresolvinglist *whenLLPrivacyisenabled.
*/
err = hci_le_set_addr_resolution_enable_sync(hdev, 0x00); if (err) {
bt_dev_err(hdev, "Unable to disable LL privacy: %d", err); goto done;
}
/* Force address filtering if PA Sync is in progress */ if (hci_dev_test_flag(hdev, HCI_PA_SYNC)) { struct hci_conn *conn;
conn = hci_conn_hash_lookup_create_pa_sync(hdev); if (conn) { struct conn_params pa;
/* Go through the current accept list programmed into the *controlleronebyoneandcheckifthataddressisconnectedoris *stillinthelistofpendingconnectionsorlistofdevicesto *report.Ifnotpresentineitherlist,thenremoveitfrom *thecontroller.
*/
list_for_each_entry_safe(b, t, &hdev->le_accept_list, list) { if (hci_conn_hash_lookup_le(hdev, &b->bdaddr, b->bdaddr_type)) continue;
/* Pointers not dereferenced, no locks needed */
pend_conn = hci_pend_le_action_lookup(&hdev->pend_le_conns,
&b->bdaddr,
b->bdaddr_type);
pend_report = hci_pend_le_action_lookup(&hdev->pend_le_reports,
&b->bdaddr,
b->bdaddr_type);
/* If the device is not likely to connect or report, *removeitfromtheacceptlist.
*/ if (!pend_conn && !pend_report) {
hci_le_del_accept_list_sync(hdev, &b->bdaddr,
b->bdaddr_type); continue;
}
num_entries++;
}
/* Since all no longer valid accept list entries have been *removed,walkthroughthelistofpendingconnections *andensurethatanynewdevicegetsprogrammedinto *thecontroller. * *Ifthelistofthedevicesislargerthanthelistof *availableacceptlistentriesinthecontroller,then *justabortandreturnfilerpolicyvaluetonotusethe *acceptlist. * *Thelistandparamsmaybemutatedwhilewewaitforevents, *somakeacopyanditerateit.
*/
for (i = 0; i < n; ++i) {
err = hci_le_add_accept_list_sync(hdev, ¶ms[i],
&num_entries); if (err) {
kvfree(params); goto done;
}
}
kvfree(params);
/* After adding all new pending connections, walk through *thelistofpendingreportsandalsoaddthesetothe *acceptlistifthereisstillspace.Abortifspacerunsout.
*/
for (i = 0; i < n; ++i) {
err = hci_le_add_accept_list_sync(hdev, ¶ms[i],
&num_entries); if (err) {
kvfree(params); goto done;
}
}
kvfree(params);
/* Use the allowlist unless the following conditions are all true: *-Wearenotcurrentlysuspending *-Thereare1ormoreADVmonitorsregisteredandit'snotoffloaded *-Interleavedscanningisnotcurrentlyusingtheallowlist
*/ if (!idr_is_empty(&hdev->adv_monitors_idr) && !hdev->suspended &&
hci_get_adv_monitor_offload_ext(hdev) == HCI_ADV_MONITOR_EXT_NONE &&
hdev->interleave_scan_state != INTERLEAVE_SCAN_ALLOWLIST)
err = -EINVAL;
done:
filter_policy = err ? 0x00 : 0x01;
/* Enable address resolution when LL Privacy is enabled. */
err = hci_le_set_addr_resolution_enable_sync(hdev, 0x01); if (err)
bt_dev_err(hdev, "Unable to enable LL privacy: %d", err);
/* Resume advertising if it was paused */ if (ll_privacy_capable(hdev))
hci_resume_advertising_sync(hdev);
/* Select filter policy to use accept list */ return filter_policy;
}
/* Check if PA Sync is in progress then select the PHY based on the *hci_conn.iso_qos.
*/ if (hci_dev_test_flag(hdev, HCI_PA_SYNC)) { struct hci_cp_le_add_to_accept_list *sent;
sent = hci_sent_cmd_data(hdev, HCI_OP_LE_ADD_TO_ACCEPT_LIST); if (sent) { struct hci_conn *conn;
/* Set require_privacy to false since no SCAN_REQ are send *duringpassivescanning.Notusingannon-resolvableaddress *hereisimportantsothatpeerdevicesusingdirect *advertisingwithouraddresswillbecorrectlyreported *bythecontroller.
*/ if (hci_update_random_address_sync(hdev, false, scan_use_rpa(hdev),
&own_addr_type)) return0;
if (hdev->enable_advmon_interleave_scan &&
hci_update_interleaved_scan_sync(hdev)) return0;
bt_dev_dbg(hdev, "interleave state %d", hdev->interleave_scan_state);
/* Adding or removing entries from the accept list must *happenbeforeenablingscanning.Thecontrollerdoes *notallowacceptlistmodificationwhilescanning.
*/
filter_policy = hci_update_accept_list_sync(hdev);
/* If suspended and filter_policy set to 0x00 (no acceptlist) then *passivescanningcannotbestartedsincethatwouldrequirethehost *tobewokenuptoprocessthereports.
*/ if (hdev->suspended && !filter_policy) { /* Check if accept list is empty then there is no need to scan *whilesuspended.
*/ if (list_empty(&hdev->le_accept_list)) return0;
/* If there are devices is the accept_list that means some *devicescouldnotbeprogrammedwhichinnon-suspendedcase *meansfilter_policyneedstobesetto0x00sothehostneeds *tofilter,butsincethisistreatingsuspendedcasewe *canignoredeviceneedinghosttofiltertoallowdevicesin *theacceptlisttobeabletowakeupthesystem.
*/
filter_policy = 0x01;
}
/* When the controller is using random resolvable addresses and *withthathavingLEprivacyenabled,thencontrollerswith *ExtendedScannerFilterPoliciessupportcannowenablesupport *forhandlingdirectedadvertising. * *Soinsteadofusingfilterpolices0x00(noacceptlist) *and0x01(acceptlistenabled)usethenewfilterpolicies *0x02(noacceptlist)and0x03(acceptlistenabled).
*/ if (hci_dev_test_flag(hdev, HCI_PRIVACY) &&
(hdev->le_features[0] & HCI_LE_EXT_SCAN_POLICY))
filter_policy |= 0x02;
/* This function controls the passive scanning based on hdev->pend_le_conns *list.IftherearependingLEconnectionwestartthebackgroundscanning, *otherwisewestopitinthefollowingsequence: * *Iftherearedevicestoscan: * *DisableScanning->UpdateAcceptList-> *ll_privacy_capable((DisableAdvertising)->DisableResolvingList-> *UpdateResolvingList->EnableResolvingList->(EnableAdvertising))-> *EnableScanning * *Otherwise: * *DisableScanning
*/ int hci_update_passive_scan_sync(struct hci_dev *hdev)
{ int err;
/* No point in doing scanning if LE support hasn't been enabled */ if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED)) return0;
/* If discovery is active don't interfere with it */ if (hdev->discovery.state != DISCOVERY_STOPPED) return0;
/* Reset RSSI and UUID filters when starting background scanning *sincethesefiltersaremeantforservicediscoveryonly. * *TheStartDiscoveryandStartServiceDiscoveryoperations *ensuretosetpropervaluesforRSSIthresholdandUUID *filterlist.Soitissafetojustresetthemhere.
*/
hci_discovery_filter_clear(hdev);
bt_dev_dbg(hdev, "ADV monitoring is %s",
hci_is_adv_monitoring(hdev) ? "on" : "off");
if (!hci_dev_test_flag(hdev, HCI_MESH) &&
list_empty(&hdev->pend_le_conns) &&
list_empty(&hdev->pend_le_reports) &&
!hci_is_adv_monitoring(hdev) &&
!hci_dev_test_flag(hdev, HCI_PA_SYNC)) { /* If there is no pending LE connections or devices *tobescannedforornoADVmonitors,weshouldstopthe *backgroundscanning.
*/
bt_dev_dbg(hdev, "stopping background scanning");
err = hci_scan_disable_sync(hdev); if (err)
bt_dev_err(hdev, "stop background scanning failed: %d",
err);
} else { /* If there is at least one pending LE connection, we should *keepthebackgroundscanrunning.
*/
/* If controller is connecting, we should not start scanning *sincesomecontrollersarenotabletoscanandconnectat *thesametime.
*/ if (hci_lookup_le_connect(hdev)) return0;
int hci_update_passive_scan(struct hci_dev *hdev)
{ /* Only queue if it would have any effect */ if (!test_bit(HCI_UP, &hdev->flags) ||
test_bit(HCI_INIT, &hdev->flags) ||
hci_dev_test_flag(hdev, HCI_SETUP) ||
hci_dev_test_flag(hdev, HCI_CONFIG) ||
hci_dev_test_flag(hdev, HCI_AUTO_OFF) ||
hci_dev_test_flag(hdev, HCI_UNREGISTER)) return0;
int hci_write_le_host_supported_sync(struct hci_dev *hdev, u8 le, u8 simul)
{ struct hci_cp_write_le_host_supported cp;
if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED) ||
!lmp_bredr_capable(hdev)) return0;
/* Check first if we already have the right host state *(hostfeaturesset)
*/ if (le == lmp_host_le_capable(hdev) &&
simul == lmp_host_le_br_capable(hdev)) return0;
if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED)) return0;
/* If RPA Resolution has not been enable yet it means the *resolvinglistisemptyandweshouldattempttoprogramthe *localIRKinordertosupportusingown_addr_type *ADDR_LE_DEV_RANDOM_RESOLVED(0x03).
*/ if (!hci_dev_test_flag(hdev, HCI_LL_RPA_RESOLUTION)) {
hci_le_add_resolve_list_sync(hdev, NULL);
hci_le_set_addr_resolution_enable_sync(hdev, 0x01);
}
/* Make sure the controller has a good default for *advertisingdata.Thisalsoappliestothecase *whereBR/EDRwastoggledduringtheAUTO_OFFphase.
*/ if (hci_dev_test_flag(hdev, HCI_ADVERTISING) &&
list_empty(&hdev->adv_instances)) { if (ext_adv_capable(hdev)) {
err = hci_setup_ext_adv_instance_sync(hdev, 0x00); if (!err)
hci_update_scan_rsp_data_sync(hdev, 0x00);
} else {
err = hci_update_adv_data_sync(hdev, 0x00); if (!err)
hci_update_scan_rsp_data_sync(hdev, 0x00);
}
if (hci_dev_test_flag(hdev, HCI_ADVERTISING))
hci_enable_advertising_sync(hdev);
}
/* Call for each tracked instance to be scheduled */
list_for_each_entry_safe(adv, tmp, &hdev->adv_instances, list)
hci_schedule_adv_instance_sync(hdev, adv->instance, true);
/* This function perform powered update HCI command sequence after the HCI init *sequencewhichendupresettingallstates,thesequenceisasfollows: * *HCI_SSP_ENABLED(EnableSSP) *HCI_LE_ENABLED(EnableLE) *HCI_LE_ENABLED(ll_privacy_capable(AddlocalIRKtoResolvingList)-> *Updateadvdata) *EnableAuthentication *lmp_bredr_capable(SetFastConnectable->SetScanType->SetClass-> *SetName->SetEIR) *HCI_FORCE_STATIC_ADDR|BDADDR_ANY&&!HCI_BREDR_ENABLED(SetStaticAddress)
*/ int hci_powered_update_sync(struct hci_dev *hdev)
{ int err;
/* Register the available SMP channels (BR/EDR and LE) only when *successfullypoweringonthecontroller.Thislate *registrationisrequiredsothatLESMPcanclearlydecideif *thepublicaddressorstaticaddressisused.
*/
smp_register(hdev);
err = hci_write_ssp_mode_sync(hdev, 0x01); if (err) return err;
err = hci_write_le_host_supported_sync(hdev, 0x01, 0x00); if (err) return err;
err = hci_powered_update_adv_sync(hdev); if (err) return err;
err = hci_write_auth_enable_sync(hdev); if (err) return err;
if (lmp_bredr_capable(hdev)) { if (hci_dev_test_flag(hdev, HCI_FAST_CONNECTABLE))
hci_write_fast_connectable_sync(hdev, true); else
hci_write_fast_connectable_sync(hdev, false);
hci_update_scan_sync(hdev);
hci_update_class_sync(hdev);
hci_update_name_sync(hdev, hdev->dev_name);
hci_update_eir_sync(hdev);
}
/* If forcing static address is in use or there is no public *addressusethestaticaddressasrandomaddress(butskip *theHCIcommandifthecurrentrandomaddressisalreadythe *staticone. * *IncaseBR/EDRhasbeendisabledonadual-modecontroller *andastaticaddresshasbeenconfigured,thenusethat *addressinsteadofthepublicBR/EDRaddress.
*/ if (hci_dev_test_flag(hdev, HCI_FORCE_STATIC_ADDR) ||
(!bacmp(&hdev->bdaddr, BDADDR_ANY) &&
!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))) { if (bacmp(&hdev->static_addr, BDADDR_ANY)) return hci_set_random_addr_sync(hdev,
&hdev->static_addr);
}
/* Read Local Commands */ staticint hci_read_local_cmds_sync(struct hci_dev *hdev)
{ /* All Bluetooth 1.2 and later controllers should support the *HCIcommandforreadingthelocalsupportedcommands. * *UnfortunatelysomecontrollersindicateBluetooth1.2support, *butdonothavesupportforthiscommand.Ifthatisthecase, *thedrivercanquirkthebehaviorandskipreadingthelocal *supportedcommands.
*/ if (hdev->hci_ver > BLUETOOTH_VER_1_1 &&
!hci_test_quirk(hdev, HCI_QUIRK_BROKEN_LOCAL_COMMANDS)) return __hci_cmd_sync_status(hdev, HCI_OP_READ_LOCAL_COMMANDS, 0, NULL, HCI_CMD_TIMEOUT);
return0;
}
staticint hci_init1_sync(struct hci_dev *hdev)
{ int err;
bt_dev_dbg(hdev, "");
/* Reset */ if (!hci_test_quirk(hdev, HCI_QUIRK_RESET_ON_CLOSE)) {
err = hci_reset_sync(hdev); if (err) return err;
}
staticint hci_clear_event_filter_sync(struct hci_dev *hdev)
{ if (!hci_dev_test_flag(hdev, HCI_EVENT_FILTER_CONFIGURED)) return0;
/* In theory the state machine should not reach here unless *ahci_set_event_filter_sync()callsucceeds,butwedo *thecheckbothforparityandasafuturereminder.
*/ if (hci_test_quirk(hdev, HCI_QUIRK_BROKEN_FILTER_CLEAR_ALL)) return0;
/* Enable SCO flow control if supported */ staticint hci_write_sync_flowctl_sync(struct hci_dev *hdev)
{ struct hci_cp_write_sync_flowctl cp; int err;
/* Check if the controller supports SCO and HCI_OP_WRITE_SYNC_FLOWCTL */ if (!lmp_sco_capable(hdev) || !(hdev->commands[10] & BIT(4)) ||
!hci_test_quirk(hdev, HCI_QUIRK_SYNC_FLOWCTL_SUPPORTED)) return0;
if (!lmp_ssp_capable(hdev) || !hci_dev_test_flag(hdev, HCI_SSP_ENABLED)) return0;
/* When SSP is available, then the host features page *shouldalsobeavailableaswell.Howeversome *controllerslistthemax_pageas0aslongasSSP *hasnotbeenenabled.Toachieveproperdebugging *output,forcetheminimummax_pageto1atleast.
*/
hdev->max_page = 0x01;
if (!lmp_inq_rssi_capable(hdev) &&
!hci_test_quirk(hdev, HCI_QUIRK_FIXUP_INQUIRY_MODE)) return0;
/* If Extended Inquiry Result events are supported, then *theyareclearlypreferredoverInquiryResultwithRSSI *events.
*/
mode = lmp_ext_inq_capable(hdev) ? 0x02 : 0x01;
staticint hci_init2_sync(struct hci_dev *hdev)
{ int err;
bt_dev_dbg(hdev, "");
err = hci_init_stage_sync(hdev, hci_init2); if (err) return err;
if (lmp_bredr_capable(hdev)) {
err = hci_init_stage_sync(hdev, br_init2); if (err) return err;
} else {
hci_dev_clear_flag(hdev, HCI_BREDR_ENABLED);
}
if (lmp_le_capable(hdev)) {
err = hci_init_stage_sync(hdev, le_init2); if (err) return err; /* LE-only controllers have LE implicitly enabled */ if (!lmp_bredr_capable(hdev))
hci_dev_set_flag(hdev, HCI_LE_ENABLED);
}
return0;
}
staticint hci_set_event_mask_sync(struct hci_dev *hdev)
{ /* The second byte is 0xff instead of 0x9f (two reserved bits *disabled)sinceaBroadcom1.2dongledoesn'trespondtothe *commandotherwise.
*/
u8 events[8] = { 0xff, 0xff, 0xfb, 0xff, 0x00, 0x00, 0x00, 0x00 };
/* CSR 1.1 dongles does not accept any bitfield so don't try to set *anyeventmaskforpre1.2devices.
*/ if (hdev->hci_ver < BLUETOOTH_VER_1_2) return0;
/* Don't set Disconnect Complete and mode change when *suspendedasthatwouldwakeupthehostwhendisconnecting *duetosuspend.
*/ if (hdev->suspended) {
events[0] &= 0xef;
events[2] &= 0xf7;
}
} else { /* Use a different default for LE-only devices */
memset(events, 0, sizeof(events));
events[1] |= 0x20; /* Command Complete */
events[1] |= 0x40; /* Command Status */
events[1] |= 0x80; /* Hardware Error */
/* If the controller supports the Disconnect command, enable *thecorrespondingevent.Inadditionenablepacketflow *controlrelatedevents.
*/ if (hdev->commands[0] & 0x20) { /* Don't set Disconnect Complete when suspended as that *wouldwakeupthehostwhendisconnectingdueto *suspend.
*/ if (!hdev->suspended)
events[0] |= 0x10; /* Disconnection Complete */
events[2] |= 0x04; /* Number of Completed Packets */
events[3] |= 0x02; /* Data Buffer Overflow */
}
/* If the controller supports the Read Remote Version *Informationcommand,enablethecorrespondingevent.
*/ if (hdev->commands[2] & 0x80)
events[1] |= 0x08; /* Read Remote Version Information *Complete
*/
if (lmp_rswitch_capable(hdev))
link_policy |= HCI_LP_RSWITCH; if (lmp_hold_capable(hdev))
link_policy |= HCI_LP_HOLD; if (lmp_sniff_capable(hdev))
link_policy |= HCI_LP_SNIFF; if (lmp_park_capable(hdev))
link_policy |= HCI_LP_PARK;
staticint hci_read_page_scan_type_sync(struct hci_dev *hdev)
{ /* Some older Broadcom based Bluetooth 1.2 controllers do not *supporttheReadPageScanTypecommand.Checksupportfor *thiscommandinthebitmaskofsupportedcommands.
*/ if (!(hdev->commands[13] & 0x01) ||
hci_test_quirk(hdev, HCI_QUIRK_BROKEN_READ_PAGE_SCAN_TYPE)) return0;
if (hdev->le_features[0] & HCI_LE_ENCRYPTION)
events[0] |= 0x10; /* LE Long Term Key Request */
/* If controller supports the Connection Parameters Request *LinkLayerProcedure,enablethecorrespondingevent.
*/ if (hdev->le_features[0] & HCI_LE_CONN_PARAM_REQ_PROC) /* LE Remote Connection Parameter Request */
events[0] |= 0x20;
/* If the controller supports the Data Length Extension *feature,enablethecorrespondingevent.
*/ if (hdev->le_features[0] & HCI_LE_DATA_LEN_EXT)
events[0] |= 0x40; /* LE Data Length Change */
/* If the controller supports LL Privacy feature or LE Extended Adv, *enablethecorrespondingevent.
*/ if (use_enhanced_conn_complete(hdev))
events[1] |= 0x02; /* LE Enhanced Connection Complete */
/* Mark Device Privacy if Privacy Mode is supported */ if (privacy_mode_capable(hdev))
hdev->conn_flags |= HCI_CONN_FLAG_DEVICE_PRIVACY;
/* Mark Address Resolution if LL Privacy is supported */ if (ll_privacy_capable(hdev))
hdev->conn_flags |= HCI_CONN_FLAG_ADDRESS_RESOLUTION;
/* If the controller supports Extended Scanner Filter *Policies,enablethecorrespondingevent.
*/ if (hdev->le_features[0] & HCI_LE_EXT_SCAN_POLICY)
events[1] |= 0x04; /* LE Direct Advertising Report */
/* If the controller supports Channel Selection Algorithm #2 *feature,enablethecorrespondingevent.
*/ if (hdev->le_features[1] & HCI_LE_CHAN_SEL_ALG2)
events[2] |= 0x08; /* LE Channel Selection Algorithm */
/* If the controller supports the LE Set Scan Enable command, *enablethecorrespondingadvertisingreportevent.
*/ if (hdev->commands[26] & 0x08)
events[0] |= 0x02; /* LE Advertising Report */
/* If the controller supports the LE Create Connection *command,enablethecorrespondingevent.
*/ if (hdev->commands[26] & 0x10)
events[0] |= 0x01; /* LE Connection Complete */
/* If the controller supports the LE Connection Update *command,enablethecorrespondingevent.
*/ if (hdev->commands[27] & 0x04)
events[0] |= 0x04; /* LE Connection Update Complete */
/* If the controller supports the LE Read Remote Used Features *command,enablethecorrespondingevent.
*/ if (hdev->commands[27] & 0x20) /* LE Read Remote Used Features Complete */
events[0] |= 0x08;
/* If the controller supports the LE Read Local P-256 *PublicKeycommand,enablethecorrespondingevent.
*/ if (hdev->commands[34] & 0x02) /* LE Read Local P-256 Public Key Complete */
events[0] |= 0x80;
/* If the controller supports the LE Generate DHKey *command,enablethecorrespondingevent.
*/ if (hdev->commands[34] & 0x04)
events[1] |= 0x01; /* LE Generate DHKey Complete */
/* If the controller supports the LE Set Default PHY or *LESetPHYcommands,enablethecorrespondingevent.
*/ if (hdev->commands[35] & (0x20 | 0x40))
events[1] |= 0x08; /* LE PHY Update Complete */
/* If the controller supports LE Set Extended Scan Parameters *andLESetExtendedScanEnablecommands,enablethe *correspondingevent.
*/ if (use_ext_scan(hdev))
events[1] |= 0x10; /* LE Extended Advertising Report */
/* If the controller supports the LE Extended Advertising *command,enablethecorrespondingevent.
*/ if (ext_adv_capable(hdev))
events[2] |= 0x02; /* LE Advertising Set Terminated */
if (cis_capable(hdev)) {
events[3] |= 0x01; /* LE CIS Established */ if (cis_peripheral_capable(hdev))
events[3] |= 0x02; /* LE CIS Request */
}
if (bis_capable(hdev)) {
events[1] |= 0x20; /* LE PA Report */
events[1] |= 0x40; /* LE PA Sync Established */
events[3] |= 0x04; /* LE Create BIG Complete */
events[3] |= 0x08; /* LE Terminate BIG Complete */
events[3] |= 0x10; /* LE BIG Sync Established */
events[3] |= 0x20; /* LE BIG Sync Loss */
events[4] |= 0x02; /* LE BIG Info Advertising Report */
}
/* Read LE Maximum Data Length */ staticint hci_le_read_max_data_len_sync(struct hci_dev *hdev)
{ if (!(hdev->le_features[0] & HCI_LE_DATA_LEN_EXT)) return0;
/* Read LE Number of Supported Advertising Sets */ staticint hci_le_read_num_support_adv_sets_sync(struct hci_dev *hdev)
{ if (!ext_adv_capable(hdev)) return0;
/* Some Broadcom based Bluetooth controllers do not support the *DeleteStoredLinkKeycommand.Theyareclearlyindicatingits *absenceinthebitmaskofsupportedcommands. * *Checkthesupportedcommandsandonlyifthecommandismarked *assupportedsendit.Ifnotsupportedassumethatthecontroller *doesnothaveactualsupportforstoredlinkkeyswhichmakesthis *commandredundantanyway. * *Somecontrollersindicatethattheysupporthandlingdeleting *storedlinkkeys,buttheydon't.Thequirkletsadriver *justdisablethiscommand.
*/ if (!(hdev->commands[6] & 0x80) ||
hci_test_quirk(hdev, HCI_QUIRK_BROKEN_STORED_LINK_KEY)) return0;
/* Some Broadcom based controllers indicate support for Set Event *MaskPage2command,butthenactuallydonotsupportit.Since *thedefaultvalueisallbitssettozero,thecommandisonly *requirediftheeventmaskhastobechanged.Incasenochange *totheeventmaskisneeded,skipthiscommand.
*/ if (!changed) return0;
/* Read local codec list if the HCI command is supported */ staticint hci_read_local_codecs_sync(struct hci_dev *hdev)
{ if (hdev->commands[45] & 0x04)
hci_read_supported_codecs_v2(hdev); elseif (hdev->commands[29] & 0x20)
hci_read_supported_codecs(hdev);
return0;
}
/* Read local pairing options if the HCI command is supported */ staticint hci_read_local_pairing_opts_sync(struct hci_dev *hdev)
{ if (!(hdev->commands[41] & 0x08)) return0;
/* Get MWS transport configuration if the HCI command is supported */ staticint hci_get_mws_transport_config_sync(struct hci_dev *hdev)
{ if (!mws_transport_config_capable(hdev)) return0;
/* Check for Synchronization Train support */ staticint hci_read_sync_train_params_sync(struct hci_dev *hdev)
{ if (!lmp_sync_train_capable(hdev)) return0;
/* Set Suggested Default Data Length to maximum if supported */ staticint hci_le_set_write_def_data_len_sync(struct hci_dev *hdev)
{ struct hci_cp_le_write_def_data_len cp;
if (!(hdev->le_features[0] & HCI_LE_DATA_LEN_EXT)) return0;
/* Set Default PHY parameters if command is supported, enables all supported *PHYsaccordingtotheLEFeaturesbits.
*/ staticint hci_le_set_default_phy_sync(struct hci_dev *hdev)
{ struct hci_cp_le_set_default_phy cp;
if (!(hdev->commands[35] & 0x20)) { /* If the command is not supported it means only 1M PHY is *supported.
*/
hdev->le_tx_def_phys = HCI_LE_SET_PHY_1M;
hdev->le_rx_def_phys = HCI_LE_SET_PHY_1M; return0;
}
staticint hci_init4_sync(struct hci_dev *hdev)
{ int err;
bt_dev_dbg(hdev, "");
err = hci_init_stage_sync(hdev, hci_init4); if (err) return err;
if (lmp_le_capable(hdev)) return hci_init_stage_sync(hdev, le_init4);
return0;
}
staticint hci_init_sync(struct hci_dev *hdev)
{ int err;
err = hci_init1_sync(hdev); if (err < 0) return err;
if (hci_dev_test_flag(hdev, HCI_SETUP))
hci_debugfs_create_basic(hdev);
err = hci_init2_sync(hdev); if (err < 0) return err;
err = hci_init3_sync(hdev); if (err < 0) return err;
err = hci_init4_sync(hdev); if (err < 0) return err;
/* This function is only called when the controller is actually in *configuredstate.Whenthecontrollerismarkedasunconfigured, *thisinitializationprocedureisnotrun. * *Itmeansthatitispossiblethatacontrollerrunsthroughits *setupphaseandthendiscoversmissingsettings.Ifthatisthe *case,thenthisfunctionwillnotbecalled.Itthenwillonly *becalledduringtheconfigphase. * *Soonlywheninsetupphaseorconfigphase,createthedebugfs *entriesandregistertheSMPchannels.
*/ if (!hci_dev_test_flag(hdev, HCI_SETUP) &&
!hci_dev_test_flag(hdev, HCI_CONFIG)) return0;
if (hci_dev_test_and_set_flag(hdev, HCI_DEBUGFS_CREATED)) return0;
hci_debugfs_create_common(hdev);
if (lmp_bredr_capable(hdev))
hci_debugfs_create_bredr(hdev);
if (lmp_le_capable(hdev))
hci_debugfs_create_le(hdev);
staticconststruct { unsignedlong quirk; constchar *desc;
} hci_broken_table[] = {
HCI_QUIRK_BROKEN(LOCAL_COMMANDS, "HCI Read Local Supported Commands not supported"),
HCI_QUIRK_BROKEN(STORED_LINK_KEY, "HCI Delete Stored Link Key command is advertised, " "but not supported."),
HCI_QUIRK_BROKEN(ERR_DATA_REPORTING, "HCI Read Default Erroneous Data Reporting command is " "advertised, but not supported."),
HCI_QUIRK_BROKEN(READ_TRANSMIT_POWER, "HCI Read Transmit Power Level command is advertised, " "but not supported."),
HCI_QUIRK_BROKEN(FILTER_CLEAR_ALL, "HCI Set Event Filter command not supported."),
HCI_QUIRK_BROKEN(ENHANCED_SETUP_SYNC_CONN, "HCI Enhanced Setup Synchronous Connection command is " "advertised, but not supported."),
HCI_QUIRK_BROKEN(SET_RPA_TIMEOUT, "HCI LE Set Random Private Address Timeout command is " "advertised, but not supported."),
HCI_QUIRK_BROKEN(EXT_CREATE_CONN, "HCI LE Extended Create Connection command is " "advertised, but not supported."),
HCI_QUIRK_BROKEN(WRITE_AUTH_PAYLOAD_TIMEOUT, "HCI WRITE AUTH PAYLOAD TIMEOUT command leads " "to unexpected SMP errors when pairing " "and will not be used."),
HCI_QUIRK_BROKEN(LE_CODED, "HCI LE Coded PHY feature bit is set, " "but its usage is not supported.")
};
/* This function handles hdev setup stage: * *Callshdev->setup *SetupaddressifHCI_QUIRK_USE_BDADDR_PROPERTYisset.
*/ staticint hci_dev_setup_sync(struct hci_dev *hdev)
{ int ret = 0; bool invalid_bdaddr;
size_t i;
if (!hci_dev_test_flag(hdev, HCI_SETUP) &&
!hci_test_quirk(hdev, HCI_QUIRK_NON_PERSISTENT_SETUP)) return0;
bt_dev_dbg(hdev, "");
hci_sock_dev_event(hdev, HCI_DEV_SETUP);
if (hdev->setup)
ret = hdev->setup(hdev);
for (i = 0; i < ARRAY_SIZE(hci_broken_table); i++) { if (hci_test_quirk(hdev, hci_broken_table[i].quirk))
bt_dev_warn(hdev, "%s", hci_broken_table[i].desc);
}
/* The transport driver can set the quirk to mark the *BD_ADDRinvalidbeforecreatingtheHCIdeviceorin *itssetupcallback.
*/
invalid_bdaddr = hci_test_quirk(hdev, HCI_QUIRK_INVALID_BDADDR) ||
hci_test_quirk(hdev, HCI_QUIRK_USE_BDADDR_PROPERTY); if (!ret) { if (hci_test_quirk(hdev, HCI_QUIRK_USE_BDADDR_PROPERTY) &&
!bacmp(&hdev->public_addr, BDADDR_ANY))
hci_dev_get_bd_addr_from_property(hdev);
if (invalid_bdaddr && bacmp(&hdev->public_addr, BDADDR_ANY) &&
hdev->set_bdaddr) {
ret = hdev->set_bdaddr(hdev, &hdev->public_addr); if (!ret)
invalid_bdaddr = false;
}
}
/* The transport driver can set these quirks before *creatingtheHCIdeviceorinitssetupcallback. * *FortheinvalidBD_ADDRquirkitispossiblethat *itbecomesavalidaddressifthebootloaderdoes *provideit(seeabove). * *Incaseanyofthemisset,thecontrollerhasto *startupasunconfigured.
*/ if (hci_test_quirk(hdev, HCI_QUIRK_EXTERNAL_CONFIG) ||
invalid_bdaddr)
hci_dev_set_flag(hdev, HCI_UNCONFIGURED);
/* For an unconfigured controller it is required to *readatleasttheversioninformationprovidedby *theReadLocalVersionInformationcommand. * *Iftheset_bdaddrdrivercallbackisprovided,then *alsotheoriginalBluetoothpublicdeviceaddress *willbereadusingtheReadBDAddresscommand.
*/ if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED)) return hci_unconf_init_sync(hdev);
return ret;
}
/* This function handles hdev init stage: * *Callshci_dev_setup_synctoperformsetupstage *Callshci_init_synctoperformHCIcommandinitsequence
*/ staticint hci_dev_init_sync(struct hci_dev *hdev)
{ int ret;
if (hci_dev_test_flag(hdev, HCI_CONFIG)) { /* If public address change is configured, ensure that *theaddressgetsprogrammed.Ifthedriverdoesnot *supportchangingthepublicaddress,failthepower *onprocedure.
*/ if (bacmp(&hdev->public_addr, BDADDR_ANY) &&
hdev->set_bdaddr)
ret = hdev->set_bdaddr(hdev, &hdev->public_addr); else
ret = -EADDRNOTAVAIL;
}
if (!ret) { if (!hci_dev_test_flag(hdev, HCI_UNCONFIGURED) &&
!hci_dev_test_flag(hdev, HCI_USER_CHANNEL)) {
ret = hci_init_sync(hdev); if (!ret && hdev->post_init)
ret = hdev->post_init(hdev);
}
}
/* If the HCI Reset command is clearing all diagnostic settings, *thentheyneedtobereprogrammedaftertheinitprocedure *completed.
*/ if (hci_test_quirk(hdev, HCI_QUIRK_NON_PERSISTENT_DIAG) &&
!hci_dev_test_flag(hdev, HCI_USER_CHANNEL) &&
hci_dev_test_flag(hdev, HCI_VENDOR_DIAG) && hdev->set_diag)
ret = hdev->set_diag(hdev, true);
if (!hci_dev_test_flag(hdev, HCI_USER_CHANNEL)) {
msft_do_open(hdev);
aosp_do_open(hdev);
}
clear_bit(HCI_INIT, &hdev->flags);
return ret;
}
int hci_dev_open_sync(struct hci_dev *hdev)
{ int ret;
bt_dev_dbg(hdev, "");
if (hci_dev_test_flag(hdev, HCI_UNREGISTER)) {
ret = -ENODEV; goto done;
}
if (!hci_dev_test_flag(hdev, HCI_SETUP) &&
!hci_dev_test_flag(hdev, HCI_CONFIG)) { /* Check for rfkill but allow the HCI setup stage to *proceed(whichinitselfdoesn'tcauseanyRFactivity).
*/ if (hci_dev_test_flag(hdev, HCI_RFKILLED)) {
ret = -ERFKILL; goto done;
}
/* Check for valid public address or a configured static *randomaddress,butlettheHCIsetupproceedto *beabletodetermineifthereisapublicaddress *ornot. * *Incaseofuserchannelusage,itisnotimportant *ifapublicaddressorstaticrandomaddressis *available.
*/ if (!hci_dev_test_flag(hdev, HCI_USER_CHANNEL) &&
!bacmp(&hdev->bdaddr, BDADDR_ANY) &&
!bacmp(&hdev->static_addr, BDADDR_ANY)) {
ret = -EADDRNOTAVAIL; goto done;
}
}
if (test_bit(HCI_UP, &hdev->flags)) {
ret = -EALREADY; goto done;
}
/* Since hci_rx_work() is possible to awake new cmd_work *itshouldbeflushedfirsttoavoidunexpectedcallof *hci_cmd_work()
*/
flush_work(&hdev->rx_work);
flush_work(&hdev->cmd_work);
staticint hci_dev_shutdown(struct hci_dev *hdev)
{ int err = 0; /* Similar to how we first do setup and then set the exclusive access *bitforuserspace,wemustfirstunsetuserchannelandthencleanup. *Otherwise,thekernelcan'tproperlyusethehcichanneltocleanup *thecontroller(someshutdownroutinesrequiresendingadditional *commandstothecontrollerforexample).
*/ bool was_userchannel =
hci_dev_test_and_clear_flag(hdev, HCI_USER_CHANNEL);
if (!hci_dev_test_flag(hdev, HCI_UNREGISTER) &&
test_bit(HCI_UP, &hdev->flags)) { /* Execute vendor specific shutdown routine */ if (hdev->shutdown)
err = hdev->shutdown(hdev);
}
if (was_userchannel)
hci_dev_set_flag(hdev, HCI_USER_CHANNEL);
return err;
}
int hci_dev_close_sync(struct hci_dev *hdev)
{ bool auto_off; int err = 0;
if (!auto_off && !hci_dev_test_flag(hdev, HCI_USER_CHANNEL) &&
hci_dev_test_flag(hdev, HCI_MGMT))
__mgmt_power_off(hdev);
hci_inquiry_cache_flush(hdev);
hci_pend_le_actions_clear(hdev);
hci_conn_hash_flush(hdev); /* Prevent data races on hdev->smp_data or hdev->smp_bredr_data */
smp_unregister(hdev);
hci_dev_unlock(hdev);
hci_sock_dev_event(hdev, HCI_DEV_DOWN);
if (!hci_dev_test_flag(hdev, HCI_USER_CHANNEL)) {
aosp_do_close(hdev);
msft_do_close(hdev);
}
/* This function perform power on HCI command sequence as follows: * *Ifcontrollerisalreadyup(HCI_UP)performshci_powered_update_sync *sequenceotherwiserunhci_dev_open_syncwhichwillfollowwith *hci_powered_update_syncaftertheinitsequenceiscompleted.
*/ staticint hci_power_on_sync(struct hci_dev *hdev)
{ int err;
err = hci_dev_open_sync(hdev); if (err < 0) return err;
/* During the HCI setup phase, a few error conditions are *ignoredandtheyneedtobecheckednow.Iftheyarestill *valid,itisimportanttoreturnthedevicebackoff.
*/ if (hci_dev_test_flag(hdev, HCI_RFKILLED) ||
hci_dev_test_flag(hdev, HCI_UNCONFIGURED) ||
(!bacmp(&hdev->bdaddr, BDADDR_ANY) &&
!bacmp(&hdev->static_addr, BDADDR_ANY))) {
hci_dev_clear_flag(hdev, HCI_AUTO_OFF);
hci_dev_close_sync(hdev);
} elseif (hci_dev_test_flag(hdev, HCI_AUTO_OFF)) {
queue_delayed_work(hdev->req_workqueue, &hdev->power_off,
HCI_AUTO_OFF_TIMEOUT);
}
if (hci_dev_test_and_clear_flag(hdev, HCI_SETUP)) { /* For unconfigured devices, set the HCI_RAW flag *sothatuserspacecaneasilyidentifythem.
*/ if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED))
set_bit(HCI_RAW, &hdev->flags);
/* For fully configured devices, this will send *theIndexAddedevent.Forunconfigureddevices, *itwillsendUnconfiguedIndexAddedevent. * *DeviceswithHCI_QUIRK_RAW_DEVICEareignored *andnoeventwillbesend.
*/
mgmt_index_added(hdev);
} elseif (hci_dev_test_and_clear_flag(hdev, HCI_CONFIG)) { /* When the controller is now configured, then it *isimportanttocleartheHCI_RAWflag.
*/ if (!hci_dev_test_flag(hdev, HCI_UNCONFIGURED))
clear_bit(HCI_RAW, &hdev->flags);
/* Powering on the controller with HCI_CONFIG set only *happenswiththetransitionfromunconfiguredto *configured.ThiswillsendtheIndexAddedevent.
*/
mgmt_index_added(hdev);
}
if (conn->type == BIS_LINK || conn->type == PA_LINK) { /* This is a BIS connection, hci_conn_del will *dothenecessarycleanup.
*/
hci_dev_lock(hdev);
hci_conn_failed(conn, reason);
hci_dev_unlock(hdev);
/* Wait for HCI_EV_DISCONN_COMPLETE, not HCI_EV_CMD_STATUS, when the *reasonisanythingbutHCI_ERROR_REMOTE_POWER_OFF.Thisreasonis *usedwhensuspendingorpoweringoff,wherewedon'twanttowait *forthepeer'sresponse.
*/ if (reason != HCI_ERROR_REMOTE_POWER_OFF) return __hci_cmd_sync_status_sk(hdev, HCI_OP_DISCONNECT, sizeof(cp), &cp,
HCI_EV_DISCONN_COMPLETE,
HCI_CMD_TIMEOUT, NULL);
if (conn->type == CIS_LINK) { /* BLUETOOTH CORE SPECIFICATION Version 5.3 | Vol 4, Part E *page1857: * *IfthiscommandisissuedforaCISontheCentralandthe *CISissuccessfullyterminatedbeforebeingestablished, *thenanHCI_LE_CIS_Establishedeventshallalsobesentfor *thisCISwiththeStatusOperationCancelledbyHost(0x44).
*/ if (test_bit(HCI_CONN_CREATE_CIS, &conn->flags)) return hci_disconnect_sync(hdev, conn, reason);
/* CIS with no Create CIS sent have nothing to cancel */ return HCI_ERROR_LOCAL_HOST_TERM;
}
if (conn->type == BIS_LINK || conn->type == PA_LINK) { /* There is no way to cancel a BIS without terminating the BIG *whichisdonelateronconnectioncleanup.
*/ return0;
}
if (hdev->hci_ver < BLUETOOTH_VER_1_2) return0;
/* Wait for HCI_EV_CONN_COMPLETE, not HCI_EV_CMD_STATUS, when the *reasonisanythingbutHCI_ERROR_REMOTE_POWER_OFF.Thisreasonis *usedwhensuspendingorpoweringoff,wherewedon'twanttowait *forthepeer'sresponse.
*/ if (reason != HCI_ERROR_REMOTE_POWER_OFF) return __hci_cmd_sync_status_sk(hdev, HCI_OP_CREATE_CONN_CANCEL, 6, &conn->dst,
HCI_EV_CONN_COMPLETE,
HCI_CMD_TIMEOUT, NULL);
/* SCO rejection has its own limited set of *allowederrorvalues(0x0D-0x0F).
*/ if (reason < 0x0d || reason > 0x0f)
cp.reason = HCI_ERROR_REJ_LIMITED_RESOURCES;
switch (conn->state) { case BT_CONNECTED: case BT_CONFIG:
err = hci_disconnect_sync(hdev, conn, reason); break; case BT_CONNECT:
err = hci_connect_cancel_sync(hdev, conn, reason); break; case BT_CONNECT2:
err = hci_reject_conn_sync(hdev, conn, reason); break; case BT_OPEN: case BT_BOUND: break; default:
disconnect = true; break;
}
hci_dev_lock(hdev);
/* Check if the connection has been cleaned up concurrently */
c = hci_conn_hash_lookup_handle(hdev, handle); if (!c || c != conn) {
err = 0; goto unlock;
}
/* Cleanup hci_conn object if it cannot be cancelled as it *likelymeansthecontrollerandhoststackareoutofsync *orincaseofLEitwasstillscanningsoitcanbecleanup *safely.
*/ if (disconnect) {
conn->state = BT_CLOSED;
hci_disconn_cfm(conn, reason);
hci_conn_del(conn);
} else {
hci_conn_failed(conn, reason);
}
rcu_read_lock(); while ((conn = list_first_or_null_rcu(head, struct hci_conn, list))) { /* Make sure the connection is not freed while unlocking */
conn = hci_conn_get(conn);
rcu_read_unlock(); /* Disregard possible errors since hci_conn_del shall have been *calledevenincaseoferrorshadoccurredsinceitwould *thencausehci_conn_failedtobecalledwhichcalls *hci_conn_delinternally.
*/
hci_abort_conn_sync(hdev, conn, reason);
hci_conn_put(conn);
rcu_read_lock();
}
rcu_read_unlock();
return0;
}
/* This function perform power off HCI command sequence as follows: * *ClearAdvertising *StopDiscovery *Disconnectallconnections *hci_dev_close_sync
*/ staticint hci_power_off_sync(struct hci_dev *hdev)
{ int err;
/* If controller is already down there is nothing to do */ if (!test_bit(HCI_UP, &hdev->flags)) return0;
hci_dev_set_flag(hdev, HCI_POWERING_DOWN);
if (test_bit(HCI_ISCAN, &hdev->flags) ||
test_bit(HCI_PSCAN, &hdev->flags)) {
err = hci_write_scan_enable_sync(hdev, 0x00); if (err) goto out;
}
err = hci_clear_adv_sync(hdev, NULL, false); if (err) goto out;
err = hci_stop_discovery_sync(hdev); if (err) goto out;
/* Terminated due to Power Off */
err = hci_disconnect_all_sync(hdev, HCI_ERROR_REMOTE_POWER_OFF); if (err) goto out;
int hci_update_discoverable_sync(struct hci_dev *hdev)
{ int err = 0;
if (hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
err = hci_write_iac_sync(hdev); if (err) return err;
err = hci_update_scan_sync(hdev); if (err) return err;
err = hci_update_class_sync(hdev); if (err) return err;
}
/* Advertising instances don't use the global discoverable setting, so *onlyupdateADifadvertisingwasenabledusingSetAdvertising.
*/ if (hci_dev_test_flag(hdev, HCI_ADVERTISING)) {
err = hci_update_adv_data_sync(hdev, 0x00); if (err) return err;
/* Discoverable mode affects the local advertising *addressinlimitedprivacymode.
*/ if (hci_dev_test_flag(hdev, HCI_LIMITED_PRIVACY)) { if (ext_adv_capable(hdev))
err = hci_start_ext_adv_sync(hdev, 0x00); else
err = hci_enable_advertising_sync(hdev);
}
}
int hci_update_discoverable(struct hci_dev *hdev)
{ /* Only queue if it would have any effect */ if (hdev_is_powered(hdev) &&
hci_dev_test_flag(hdev, HCI_ADVERTISING) &&
hci_dev_test_flag(hdev, HCI_DISCOVERABLE) &&
hci_dev_test_flag(hdev, HCI_LIMITED_PRIVACY)) return hci_cmd_sync_queue(hdev, update_discoverable_sync, NULL,
NULL);
return0;
}
int hci_update_connectable_sync(struct hci_dev *hdev)
{ int err;
err = hci_update_scan_sync(hdev); if (err) return err;
/* If BR/EDR is not enabled and we disable advertising as a *by-productofdisablingconnectable,weneedtoupdatethe *advertisingflags.
*/ if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
err = hci_update_adv_data_sync(hdev, hdev->cur_adv_instance);
/* Update the advertising parameters if necessary */ if (hci_dev_test_flag(hdev, HCI_ADVERTISING) ||
!list_empty(&hdev->adv_instances)) { if (ext_adv_capable(hdev))
err = hci_start_ext_adv_sync(hdev,
hdev->cur_adv_instance); else
err = hci_enable_advertising_sync(hdev);
staticint hci_active_scan_sync(struct hci_dev *hdev, uint16_t interval)
{
u8 own_addr_type; /* Accept list is not used for discovery */
u8 filter_policy = 0x00; /* Default is to enable duplicates filter */
u8 filter_dup = LE_SCAN_FILTER_DUP_ENABLE; int err;
bt_dev_dbg(hdev, "");
/* If controller is scanning, it means the passive scanning is *running.Thus,weshouldtemporarilystopitinordertosetthe *discoveryscanningparameters.
*/
err = hci_scan_disable_sync(hdev); if (err) {
bt_dev_err(hdev, "Unable to disable scanning: %d", err); return err;
}
cancel_interleave_scan(hdev);
/* Pause address resolution for active scan and stop advertising if *privacyisenabled.
*/
err = hci_pause_addr_resolution(hdev); if (err) goto failed;
/* All active scans will be done with either a resolvable private *address(whenprivacyfeaturehasbeenenabled)ornon-resolvable *privateaddress.
*/
err = hci_update_random_address_sync(hdev, true, scan_use_rpa(hdev),
&own_addr_type); if (err < 0)
own_addr_type = ADDR_LE_DEV_PUBLIC;
if (hci_is_adv_monitoring(hdev) ||
(hci_test_quirk(hdev, HCI_QUIRK_STRICT_DUPLICATE_FILTER) &&
hdev->discovery.result_filtering)) { /* Duplicate filter should be disabled when some advertisement *monitorisactivated,otherwiseAdvMoncanonlyreceiveone *advertisementforonepeer(*)duringactivescanning,and *mightreportlosstothesepeers. * *Ifcontrollerdoesstrictduplicatefilteringandthe *discoveryrequiresresultfilteringdisablescontrollerbased *filteringsincethatcancausereportsthatwouldmatchthe *hostfiltertonotbereported.
*/
filter_dup = LE_SCAN_FILTER_DUP_DISABLE;
}
switch (hdev->discovery.type) { case DISCOV_TYPE_BREDR: return hci_inquiry_sync(hdev, DISCOV_BREDR_INQUIRY_LEN, 0); case DISCOV_TYPE_INTERLEAVED: /* When running simultaneous discovery, the LE scanning time *shouldoccupythewholediscoverytimesineBR/EDRinquiry *andLEscanningarescheduledbythecontroller. * *Forinterleavingdiscoveryincomparison,BR/EDRinquiry *andLEscanningaredonesequentiallywithseparate *timeouts.
*/ if (hci_test_quirk(hdev, HCI_QUIRK_SIMULTANEOUS_DISCOVERY)) {
timeout = msecs_to_jiffies(DISCOV_LE_TIMEOUT); /* During simultaneous discovery, we double LE scan *interval.Wemustleavesometimeforthecontroller *todoBR/EDRinquiry.
*/
err = hci_start_interleaved_discovery_sync(hdev); break;
}
/* This function disables discovery and mark it as paused */ staticint hci_pause_discovery_sync(struct hci_dev *hdev)
{ int old_state = hdev->discovery.state; int err;
/* If discovery already stopped/stopping/paused there nothing to do */ if (old_state == DISCOVERY_STOPPED || old_state == DISCOVERY_STOPPING ||
hdev->discovery_paused) return0;
hci_discovery_set_state(hdev, DISCOVERY_STOPPING);
err = hci_stop_discovery_sync(hdev); if (err) return err;
if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) return0;
/* Some fake CSR controllers lock up after setting this type of *filter,soavoidsendingtherequestaltogether.
*/ if (hci_test_quirk(hdev, HCI_QUIRK_BROKEN_FILTER_CLEAR_ALL)) return0;
/* Always clear event filter when starting */
hci_clear_event_filter_sync(hdev);
list_for_each_entry(b, &hdev->accept_list, list) { if (!(b->flags & HCI_CONN_FLAG_REMOTE_WAKEUP)) continue;
bt_dev_dbg(hdev, "Adding event filters for %pMR", &b->bdaddr);
err = hci_set_event_filter_sync(hdev, HCI_FLT_CONN_SETUP,
HCI_CONN_SETUP_ALLOW_BDADDR,
&b->bdaddr,
HCI_CONN_SETUP_AUTO_ON); if (err)
bt_dev_err(hdev, "Failed to set event filter for %pMR",
&b->bdaddr); else
scan = SCAN_PAGE;
}
/* This function disables scan (BR and LE) and mark it as paused */ staticint hci_pause_scan_sync(struct hci_dev *hdev)
{ if (hdev->scanning_paused) return0;
/* Disable page scan if enabled */ if (test_bit(HCI_PSCAN, &hdev->flags))
hci_write_scan_enable_sync(hdev, SCAN_DISABLED);
hci_scan_disable_sync(hdev);
hdev->scanning_paused = true;
return0;
}
/* This function performs the HCI suspend procedures in the follow order: * *Pausediscovery(activescanning/inquiry) *PauseDirectedAdvertising/Advertising *PauseScanning(passivescanningincasediscoverywasnotactive) *Disconnectallconnections *Setsuspend_statustoBT_SUSPEND_DISCONNECTifhdevcannotwakeup *otherwise: *Updateeventmask(onlyseteventsthatareallowedtowakeupthehost) *Updateeventfilter(withdevicesmarkedwithHCI_CONN_FLAG_REMOTE_WAKEUP) *Updatepassivescanning(lowerdutycycle) *Setsuspend_statustoBT_SUSPEND_CONFIGURE_WAKE
*/ int hci_suspend_sync(struct hci_dev *hdev)
{ int err;
/* If marked as suspended there nothing to do */ if (hdev->suspended) return0;
/* Mark device as suspended */
hdev->suspended = true;
/* Pause discovery if not already stopped */
hci_pause_discovery_sync(hdev);
/* Pause other advertisements */
hci_pause_advertising_sync(hdev);
/* Prevent disconnects from causing scanning to be re-enabled */
hci_pause_scan_sync(hdev);
if (hci_conn_count(hdev)) { /* Soft disconnect everything (power off) */
err = hci_disconnect_all_sync(hdev, HCI_ERROR_REMOTE_POWER_OFF); if (err) { /* Set state to BT_RUNNING so resume doesn't notify */
hdev->suspend_state = BT_RUNNING;
hci_resume_sync(hdev); return err;
}
/* Update event mask so only the allowed event can wakeup the *host.
*/
hci_set_event_mask_sync(hdev);
}
/* Only configure accept list if disconnect succeeded and wake *isn'tbeingprevented.
*/ if (!hdev->wakeup || !hdev->wakeup(hdev)) {
hdev->suspend_state = BT_SUSPEND_DISCONNECT; return0;
}
/* Unpause to take care of updating scanning params */
hdev->scanning_paused = false;
/* Enable event filter for paired devices */
hci_update_event_filter_sync(hdev);
/* Update LE passive scan if enabled */
hci_update_passive_scan_sync(hdev);
/* This function resume scan and reset paused flag */ staticint hci_resume_scan_sync(struct hci_dev *hdev)
{ if (!hdev->scanning_paused) return0;
hdev->scanning_paused = false;
hci_update_scan_sync(hdev);
/* Reset passive scanning to normal */
hci_update_passive_scan_sync(hdev);
return0;
}
/* This function performs the HCI suspend procedures in the follow order: * *Restoreeventmask *Cleareventfilter *Updatepassivescanning(normaldutycycle) *ResumeDirectedAdvertising/Advertising *Resumediscovery(activescanning/inquiry)
*/ int hci_resume_sync(struct hci_dev *hdev)
{ /* If not marked as suspended there nothing to do */ if (!hdev->suspended) return0;
err = hci_update_random_address_sync(hdev, false, conn_use_rpa(conn),
&own_addr_type); if (err) return err;
/* Set require_privacy to false so that the remote device has a *chanceofidentifyingus.
*/
err = hci_get_random_address(hdev, false, conn_use_rpa(conn), NULL,
&own_addr_type, &random_addr); if (err) return err;
/* As per Core Spec 5.2 Vol 2, PART E, Sec 7.8.53, for *advertising_event_propertyLE_LEGACY_ADV_DIRECT_IND *doesnotsupportsadvertisingdatawhentheadvertisingsetalready *containssome,thecontrollershallreturnerroccode'Invalid *HCICommandParameters(0x12). *Soitisrequiredtoremoveadvsetforhandle0x00.sinceweuse *instance0fordirectedadv.
*/
err = hci_remove_ext_adv_instance_sync(hdev, cp.handle, NULL); if (err) return err;
err = hci_set_ext_adv_params_sync(hdev, NULL, &cp, &rp); if (err) return err;
/* Update adv data as tx power is known now */
err = hci_set_ext_adv_data_sync(hdev, cp.handle); if (err) return err;
/* Check if random address need to be updated */ if (own_addr_type == ADDR_LE_DEV_RANDOM &&
bacmp(&random_addr, BDADDR_ANY) &&
bacmp(&random_addr, &hdev->random_addr)) {
err = hci_set_adv_set_random_addr_sync(hdev, 0x00,
&random_addr); if (err) return err;
}
if (ext_adv_capable(hdev)) return hci_le_ext_directed_advertising_sync(hdev, conn);
/* Clear the HCI_LE_ADV bit temporarily so that the *hci_update_random_addressknowsthatit'ssafetogoahead *andwriteanewrandomaddress.Theflagwillbesetbackon *assoonastheSET_ADV_ENABLEHCIcommandcompletes.
*/
hci_dev_clear_flag(hdev, HCI_LE_ADV);
/* Set require_privacy to false so that the remote device has a *chanceofidentifyingus.
*/
status = hci_update_random_address_sync(hdev, false, conn_use_rpa(conn),
&own_addr_type); if (status) return status;
memset(&cp, 0, sizeof(cp));
/* Some controllers might reject command if intervals are not *withinrangeforundirectedadvertising. *BCM20702A0isknowntobeaffectedbythis.
*/
cp.min_interval = cpu_to_le16(0x0020);
cp.max_interval = cpu_to_le16(0x0020);
/* If requested to connect as peripheral use directed advertising */ if (conn->role == HCI_ROLE_SLAVE) { /* If we're active scanning and simultaneous roles is not *enabledsimplyrejecttheattempt.
*/ if (hci_dev_test_flag(hdev, HCI_LE_SCAN) &&
hdev->le_scan_type == LE_SCAN_ACTIVE &&
!hci_dev_test_flag(hdev, HCI_LE_SIMULTANEOUS_ROLES)) {
hci_conn_del(conn); return -EBUSY;
}
/* Pause advertising while doing directed advertising. */
hci_pause_advertising_sync(hdev);
/* Disable advertising if simultaneous roles is not in use. */ if (!hci_dev_test_flag(hdev, HCI_LE_SIMULTANEOUS_ROLES))
hci_pause_advertising_sync(hdev);
/* If controller is scanning, we stop it since some controllers are *notabletoscanandconnectatthesametime.Alsosetthe *HCI_LE_SCAN_INTERRUPTEDflagsothatthecommandcomplete *handlerforscandisablingknowstosetthecorrectdiscovery *state.
*/ if (hci_dev_test_flag(hdev, HCI_LE_SCAN)) {
hci_scan_disable_sync(hdev);
hci_dev_set_flag(hdev, HCI_LE_SCAN_INTERRUPTED);
}
/* Update random address, but set require_privacy to false so *thatweneverconnectwithannon-resolvableaddress.
*/
err = hci_update_random_address_sync(hdev, false, conn_use_rpa(conn),
&own_addr_type); if (err) goto done; /* Send command LE Extended Create Connection if supported */ if (use_ext_conn(hdev)) {
err = hci_le_ext_create_conn_sync(hdev, conn, own_addr_type); goto done;
}
int hci_get_random_address(struct hci_dev *hdev, bool require_privacy, bool use_rpa, struct adv_info *adv_instance,
u8 *own_addr_type, bdaddr_t *rand_addr)
{ int err;
bacpy(rand_addr, BDADDR_ANY);
/* If privacy is enabled use a resolvable private address. If *currentRPAhasexpiredthengenerateanewone.
*/ if (use_rpa) { /* If Controller supports LL Privacy use own address type is *0x03
*/ if (ll_privacy_capable(hdev))
*own_addr_type = ADDR_LE_DEV_RANDOM_RESOLVED; else
*own_addr_type = ADDR_LE_DEV_RANDOM;
if (adv_instance) { if (adv_rpa_valid(adv_instance)) return0;
} else { if (rpa_valid(hdev)) return0;
}
err = smp_generate_rpa(hdev, hdev->irk, &hdev->rpa); if (err < 0) {
bt_dev_err(hdev, "failed to generate new RPA"); return err;
}
bacpy(rand_addr, &hdev->rpa);
return0;
}
/* In case of required privacy without resolvable private address, *useannon-resolvableprivateaddress.Thisisusefulfor *non-connectableadvertising.
*/ if (require_privacy) {
bdaddr_t nrpa;
while (true) { /* The non-resolvable private address is generated *fromrandomsixbyteswiththetwomostsignificant *bitscleared.
*/
get_random_bytes(&nrpa, 6);
nrpa.b[5] &= 0x3f;
/* The non-resolvable private address shall not be *equaltothepublicaddress.
*/ if (bacmp(&hdev->bdaddr, &nrpa)) break;
}
if (!err) {
hci_connect_le_scan_cleanup(conn, 0x00); goto done;
}
/* Check if connection is still pending */ if (conn != hci_lookup_le_connect(hdev)) goto done;
/* Flush to make sure we send create conn cancel command if needed */
flush_delayed_work(&conn->le_conn_timeout);
hci_conn_failed(conn, bt_status(err));
if (!hci_conn_valid(hdev, conn)) return -ECANCELED;
if (conn->sync_handle != HCI_SYNC_HANDLE_INVALID) return -EINVAL;
if (hci_dev_test_and_set_flag(hdev, HCI_PA_SYNC)) return -EBUSY;
/* Stop scanning if SID has not been set and active scanning is enabled *soweusepassivescanningwhichwillbescanningusingtheallow *listprogrammedtocontainonlytheconnectionaddress.
*/ if (conn->sid == HCI_SID_INVALID &&
hci_dev_test_flag(hdev, HCI_LE_SCAN)) {
hci_scan_disable_sync(hdev);
hci_dev_set_flag(hdev, HCI_LE_SCAN_INTERRUPTED);
hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
}
/* Mark HCI_CONN_CREATE_PA_SYNC so hci_update_passive_scan_sync can *programtheaddressintheallowlistsoPAadvertisementscanbe *received.
*/
set_bit(HCI_CONN_CREATE_PA_SYNC, &conn->flags);
hci_update_passive_scan_sync(hdev);
/* SID has not been set listen for HCI_EV_LE_EXT_ADV_REPORT to update *it.
*/ if (conn->sid == HCI_SID_INVALID) {
err = __hci_cmd_sync_status_sk(hdev, HCI_OP_NOP, 0, NULL,
HCI_EV_LE_EXT_ADV_REPORT,
conn->conn_timeout, NULL); if (err == -ETIMEDOUT) goto done;
}
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.435Bemerkung:
(vorverarbeitet am 2026-09-28)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.