/** * Turn advertising on/off. * * Context: Link Layer task * * @param cmd * * @return int */ int ble_ll_adv_set_enable(uint8_t *cmd) { int rc; uint8_t enable; struct ble_ll_adv_sm *advsm; advsm = &g_ble_ll_adv_sm; rc = 0; enable = cmd[0]; if (enable == 1) { /* If already enabled, do nothing */ if (!advsm->enabled) { /* Start the advertising state machine */ rc = ble_ll_adv_sm_start(advsm); } } else if (enable == 0) { ble_ll_adv_sm_stop(advsm); } else { rc = BLE_ERR_INV_HCI_CMD_PARMS; } return rc; }
/** * Reset the advertising state machine. * * Context: Link Layer task * */ void ble_ll_adv_reset(void) { struct ble_ll_adv_sm *advsm; advsm = &g_ble_ll_adv_sm; /* Stop advertising state machine */ ble_ll_adv_sm_stop(advsm); /* re-initialize the advertiser state machine */ ble_ll_adv_init(); }
/** * Called when a connect request has been received. * * Context: Link Layer * * @param rxbuf * @param flags * * @return 0: no connection started. 1: connection started */ int ble_ll_adv_conn_req_rxd(uint8_t *rxbuf, struct ble_mbuf_hdr *hdr) { int valid; uint8_t pyld_len; uint8_t *inita; uint32_t endtime; struct ble_ll_adv_sm *advsm; /* Check filter policy. */ valid = 0; advsm = &g_ble_ll_adv_sm; if (advsm->adv_filter_policy & 2) { if (hdr->rxinfo.flags & BLE_MBUF_HDR_F_DEVMATCH) { /* valid connection request received */ valid = 1; } } else { /* If this is for us? */ if (!ble_ll_adv_addr_cmp(rxbuf)) { /* * Only accept connect requests from the desired address if we * are doing directed advertising */ if ((advsm->adv_type == BLE_HCI_ADV_TYPE_ADV_DIRECT_IND_HD) || (advsm->adv_type == BLE_HCI_ADV_TYPE_ADV_DIRECT_IND_LD)) { /* XXX: not sure if this works if address is random */ /* Compare addresses */ inita = rxbuf + BLE_LL_PDU_HDR_LEN; if (!memcmp(advsm->initiator_addr, inita, BLE_DEV_ADDR_LEN)) { valid = 1; } } else { valid = 1; } } } if (valid) { /* Try to start slave connection. If successful, stop advertising */ pyld_len = rxbuf[1] & BLE_ADV_PDU_HDR_LEN_MASK; endtime = hdr->beg_cputime + BLE_TX_DUR_USECS_M(pyld_len); valid = ble_ll_conn_slave_start(rxbuf, endtime); if (valid) { ble_ll_adv_sm_stop(advsm); } } return valid; }
/** * Reset the advertising state machine. * * Context: Link Layer task * */ void ble_ll_adv_reset(void) { struct ble_ll_adv_sm *advsm; advsm = &g_ble_ll_adv_sm; /* Stop advertising state machine */ ble_ll_adv_sm_stop(advsm); /* Free scan pdu's */ os_mbuf_free_chain(advsm->scan_rsp_pdu); /* re-initialize the advertiser state machine */ ble_ll_adv_init(); }
/** * Called when a connect request has been received. * * Context: Link Layer * * @param rxbuf * @param flags * * @return 0: no connection started. 1: connection started */ int ble_ll_adv_conn_req_rxd(uint8_t *rxbuf, struct ble_mbuf_hdr *hdr) { int valid; uint8_t pyld_len; #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) uint8_t resolved; #endif uint8_t addr_type; uint8_t *inita; uint8_t *ident_addr; uint32_t endtime; struct ble_ll_adv_sm *advsm; /* Check filter policy. */ valid = 0; #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) resolved = BLE_MBUF_HDR_RESOLVED(hdr); #endif advsm = &g_ble_ll_adv_sm; inita = rxbuf + BLE_LL_PDU_HDR_LEN; if (hdr->rxinfo.flags & BLE_MBUF_HDR_F_DEVMATCH) { valid = 1; if (rxbuf[0] & BLE_ADV_PDU_HDR_TXADD_MASK) { addr_type = BLE_ADDR_TYPE_RANDOM; } else { addr_type = BLE_ADDR_TYPE_PUBLIC; } /* * Only accept connect requests from the desired address if we * are doing directed advertising */ if ((advsm->adv_type == BLE_HCI_ADV_TYPE_ADV_DIRECT_IND_HD) || (advsm->adv_type == BLE_HCI_ADV_TYPE_ADV_DIRECT_IND_LD)) { ident_addr = inita; #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) if (resolved) { ident_addr = g_ble_ll_resolv_list[advsm->adv_rpa_index].rl_identity_addr; addr_type = g_ble_ll_resolv_list[advsm->adv_rpa_index].rl_addr_type; } #endif if ((addr_type != advsm->peer_addr_type) || memcmp(advsm->peer_addr, ident_addr, BLE_DEV_ADDR_LEN)) { valid = 0; } } } if (valid) { #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) if (resolved) { /* Retain the resolvable private address that we received. */ memcpy(advsm->adv_rpa, inita, BLE_DEV_ADDR_LEN); /* * Overwrite received inita with identity address since that * is used from now on. */ memcpy(inita, g_ble_ll_resolv_list[advsm->adv_rpa_index].rl_identity_addr, BLE_DEV_ADDR_LEN); /* Peer address type is an identity address */ addr_type = g_ble_ll_resolv_list[advsm->adv_rpa_index].rl_addr_type; addr_type += 2; } #endif /* Try to start slave connection. If successful, stop advertising */ pyld_len = rxbuf[1] & BLE_ADV_PDU_HDR_LEN_MASK; endtime = hdr->beg_cputime + BLE_TX_DUR_USECS_M(pyld_len); valid = ble_ll_conn_slave_start(rxbuf, endtime, addr_type); if (valid) { ble_ll_adv_sm_stop(advsm); } } return valid; }