Merge "persist: add the default numbers property array and random number generation"
diff --git a/hci.c b/hci.c
index e950217..2ec7ca1 100644
--- a/hci.c
+++ b/hci.c
@@ -1985,6 +1985,52 @@
}
/*
+ * FUNCTION: hciAdvSetTerminatedEventHandle
+ * USE: Called when we know an adv set stopped being advertised (usually due to a connection)
+ * PARAMS: advInstance - the hw instance id of the adv set
+ * aclConnId - the connection this caused (or ACL_CONN_ID_INVALID is none)
+ * RETURN: none
+ * NOTES: will take mAdvSetsLock and mConnsLock (not concurrently). If a connection is found and
+ * it is still in a BLAMING state, it will be adjusted to config state and advSet param
+ * will be filled.
+ */
+static void hciAdvSetTerminatedEventHandle(uint8_t advInstance, uint16_t aclConnId)
+{
+ hci_adv_set_t setH = 0;
+ struct hciAdvSet *t;
+
+ pthread_mutex_lock(&mAdvSetsLock);
+ for (t = mAdvSets; t; t = t->next) {
+ if (t->hwEnabled && t->hwSetNum == advInstance) {
+ t->hwEnabled = false; //even if conn not found, this set was still fingered for being the cause so it is still already off
+ setH = t->handle;
+ break;
+ }
+ }
+ pthread_mutex_unlock(&mAdvSetsLock);
+
+ if (!setH)
+ logw("Adv id not found for vendor advt change event\n");
+ else if (aclConnId != ACL_CONN_ID_INVALID) {
+
+ struct hciAclConn* conn;
+
+ pthread_mutex_lock(&mConnsLock);
+ conn = hciConnFindById(aclConnId);
+ if (!conn)
+ logw("Connection id not found for vendor advt change event\n");
+ else if (conn->state != CONN_STATE_ADV_SET_BLAMING)
+ logw("Conn is not in blaming state for vendor advt change event\n");
+ else {
+ conn->le.advSet = setH;
+ conn->state = CONN_STATE_CFG;
+ hciConnCfg(conn, CONN_CFG_STEP_LE, 0);
+ }
+ pthread_mutex_unlock(&mConnsLock);
+ }
+}
+
+/*
* FUNCTION: hciConnEvtCbk
* USE: Called with connection state events
* PARAMS: evt - the event
@@ -2066,6 +2112,10 @@
logd("ACL LE kery req for conn 0x%02x with rand 0x"FMT64"x and div 0x%02x\n", cid, CNV64(randomNum), diversifier);
if (!hciHandleConnLeLtkReq(cid, randomNum, diversifier))
loge("Failed to handle LE key req\n");
+ } else if (evtType == HCI_EVTLE_Adv_Set_Terminated) {
+ struct hciEvtLeAdvSetTerminated *req = (struct hciEvtLeAdvSetTerminated*)(meta + 1);
+
+ hciAdvSetTerminatedEventHandle(req->advSetHandle, req->status ? ACL_CONN_ID_INVALID : req->conn);
} else
return false;
} else if (evtType == HCI_EVT_Vendor) {
@@ -2079,36 +2129,8 @@
logw("Invalid event size for vendor subevent for advt change - ignored\n");
else if (sce->reason != HCI_EVTVENDOR_Android_Subevent_Advt_State_Change_Reason)
logw("Invalid reason code for vendor subevent for advt change - ignored\n");
- else {
- struct hciAclConn* conn;
- hci_adv_set_t setH = 0;
- struct hciAdvSet *t;
-
- pthread_mutex_lock(&mAdvSetsLock);
- for (t = mAdvSets; t; t = t->next) {
- if (t->hwEnabled && t->hwSetNum == sce->advInstance) {
- t->hwEnabled = false; //even if conn not found, this set was still fingered for being the cause so it is still already off
- setH = t->handle;
- break;
- }
- }
- pthread_mutex_unlock(&mAdvSetsLock);
-
- pthread_mutex_lock(&mConnsLock);
- conn = hciConnFindById(sce->connHandle);
- if (!conn)
- logw("Connection id not found for vendor advt change event\n");
- else if (!setH)
- logw("Adv id not found for vendor advt change event\n");
- else if (conn->state != CONN_STATE_ADV_SET_BLAMING)
- logw("Conn is not in blaming state for vendor advt change event\n");
- else {
- conn->le.advSet = setH;
- conn->state = CONN_STATE_CFG;
- hciConnCfg(conn, CONN_CFG_STEP_LE, 0);
- }
- pthread_mutex_unlock(&mConnsLock);
- }
+ else
+ hciAdvSetTerminatedEventHandle(sce->advInstance, sce->connHandle);
} else
return false;
} else
@@ -2859,9 +2881,10 @@
/* set event handlers for connection states */
{
static const uint8_t connEvtTypes[] = {HCI_EVT_Disconnection_Complete, HCI_EVT_Encryption_Change, HCI_EVT_Authentication_Complete,
- HCI_EVT_LE_Meta, HCI_EVT_LE_Meta, HCI_EVT_LE_Meta, HCI_EVT_Vendor, 0};
+ HCI_EVT_LE_Meta, HCI_EVT_LE_Meta, HCI_EVT_LE_Meta, HCI_EVT_Vendor, HCI_EVT_LE_Meta, 0};
static const uint16_t connEvtExtras[] = {0, 0, 0, HCI_EVTLE_Connection_Complete, HCI_EVTLE_Connection_Update_Complete,
- HCI_EVTLE_LTK_Request, HCI_EVTVENDOR_Android_Subevent_Advt_State_Change,};
+ HCI_EVTLE_LTK_Request, HCI_EVTVENDOR_Android_Subevent_Advt_State_Change,
+ HCI_EVTLE_Adv_Set_Terminated};
if (!hciSetManyEventPersistentHandlers(connEvtTypes, connEvtExtras, hciConnEvtCbk, NULL)) {
ret = -2;
diff --git a/hci.h b/hci.h
index 1e83e9d..8f756b9 100644
--- a/hci.h
+++ b/hci.h
@@ -42,9 +42,21 @@
#define HCI_DEV_NAME_LEN 248
-//this alsmost always means "max power but i don't care to specify how much exactly"
+//this almost always means "max power but i don't care to specify how much exactly"
#define HCI_ADV_TX_PWR_LVL_DONT_CARE 127
+//PHY types
+#define HCI_LE_PHY_1M 1
+#define HCI_LE_PHY_2M 2
+#define HCI_LE_PHY_CODED 3
+
+//needless fragmentation is NOT allowed for legacy ADV PDUs
+#define HCI_EXTD_ADV_DATA_OP_MIDDLE_FRAG 0 //middle fragment of a long data set
+#define HCI_EXTD_ADV_DATA_OP_FIRST_FRAG 1 //first part of a long data set
+#define HCI_EXTD_ADV_DATA_OP_LAST_FRAG 2 //last part of a long data set
+#define HCI_EXTD_ADV_DATA_OP_COMPLETE 3 //a complete adv data set
+#define HCI_EXTD_ADV_DATA_OP_UNCHANGED 4 //no data included - use old data
+
/* eir data types */
#define HCI_EIR_TYPE_FLAGS 0x01
#define HCI_EIR_TYPE_INCOMPL_LIST_UUID16 0x02
diff --git a/hci_int.h b/hci_int.h
index caacac7..c7e9ce3 100644
--- a/hci_int.h
+++ b/hci_int.h
@@ -2683,7 +2683,7 @@
struct hciLeSetExtendedAdvEnable {
uint8_t enable;
uint8_t numSets;
- struct hciLeSetExtendedAdvEnableItem sets[];
+ struct hciLeSetExtendedAdvEnableItem sets[1]; /* 1 here since then we can use this command easily to control a single set at a time, other uses can be made with more work */
} __packed;
struct hciCmplLeSetExtendedAdvEnable {
uint8_t status;
diff --git a/hci_templated_commands.h b/hci_templated_commands.h
index 142ccd3..f3ed1a4 100644
--- a/hci_templated_commands.h
+++ b/hci_templated_commands.h
@@ -7,6 +7,7 @@
#error "do not ever include this file anywhere"
#endif
+#include <alloca.h>
/*
* This generates simple SYNC functions for BT commands.
@@ -37,8 +38,7 @@
struct hciEvtCmdStatus *evt = &evtD; \
const uint8_t _ogf = ogf; \
const uint16_t _ocf = ocf; \
- const bool want_sta = true; \
- uint32_t _len = 0;
+ const bool want_sta = true;
#define HCI_SIMPLY_SYNC_WRITE(name, params, ogf, ocf) \
static int hci##name##Sync params \
@@ -50,8 +50,25 @@
struct hciCmpl##name *evt = &evtD; \
const uint8_t _ogf = ogf; \
const uint16_t _ocf = ocf; \
+ const bool want_sta = false;
+
+#define HCI_SIMPLY_SYNC_WRITE_VAR_LEN(name, params, ogf, ocf, lenParam) \
+ static int hci##name##Sync params \
+ { \
+ struct hci##name *cmd; \
+ const uint32_t cmdSz = sizeof(*cmd) + lenParam; \
+ struct hciCmpl##name evtD; \
+ struct hciCmpl##name *evt = &evtD; \
+ const uint8_t _ogf = ogf; \
+ const uint16_t _ocf = ocf; \
const bool want_sta = false; \
- uint32_t _len = 0;
+ const uint8_t varLenWriteMarker = 1; /* allow COPY_IN_VAR_LEN_DATA */ \
+ if (cmdSz > 255) { \
+ loge("attempt to call 0x%02X.%04X with %ub of data\n", \
+ _ogf, _ocf, (int)(lenParam + sizeof(struct hci##name))); \
+ return -2; \
+ } \
+ cmd = alloca(cmdSz);
#define HCI_SIMPLY_SYNC_WRITE_NOCMDPARAMS(name, ogf, ocf) \
static int hci##name##Sync (void) \
@@ -62,8 +79,7 @@
struct hciCmpl##name *evt = &evtD; \
const uint8_t _ogf = ogf; \
const uint16_t _ocf = ocf; \
- const bool want_sta = false; \
- uint32_t _len = 0;
+ const bool want_sta = false;
#define HCI_SIMPLY_SYNC_READ(name, params, ogf, ocf) \
static int hci##name##Sync params \
@@ -73,8 +89,7 @@
const uint32_t cmdSz = sizeof(*cmd); \
const uint8_t _ogf = ogf; \
const uint16_t _ocf = ocf; \
- const bool want_sta = false; \
- uint32_t _len = 0;
+ const bool want_sta = false;
#define HCI_SIMPLY_SYNC_READ_NOCMDPARAMS(name, params, ogf, ocf) \
static int hci##name##Sync params \
@@ -83,8 +98,7 @@
const uint32_t cmdSz = 0; \
const uint8_t _ogf = ogf; \
const uint16_t _ocf = ocf; \
- const bool want_sta = false; \
- uint32_t _len = 0;
+ const bool want_sta = false;
#define REQUIRE_VERSION(_v) if (mBtVer < _v) { \
loge("attempt to call 0x%02X.%04X on v%u\n", _ogf, _ocf, mBtVer); \
@@ -109,6 +123,8 @@
#define HCI_COPY_IN_U8(name) utilSetLE8(&cmd->name, name);
#define HCI_COPY_IN_BOOL(name) utilSetLE8(&cmd->name, name ? 1 : 0);
#define HCI_COPY_IN_MAC(name) memcpy(cmd->name, name, sizeof(cmd->name));
+#define HCI_COPY_IN_VAR_LEN_DATA(name,len) if (varLenWriteMarker) \
+ memcpy(cmd->name, name, len); //only allowed in HCI_SIMPLY_SYNC_WRITE_VAR_LEN
#define HCI_COPY_IN_DATA(name,len) if (len > sizeof(cmd->name)) { \
logw("Truncating "#name" to %ub\n",(int)sizeof(cmd->name)); \
len = sizeof(cmd->name); \
@@ -124,7 +140,105 @@
return (unsigned)utilGetLE8(&evt->status); \
}
+/*
+ * FUNCTION: hciLeSetExtendedAdvParamsSync
+ * USE: set extended adv params (BT5)
+ * PARAMS: advSetHandle - the adv set handle
+ * advSetProperties - adv type to use (bitfield)
+ * primaryAdvIntervalMin - minimum adv interval (in units of 0.625ms), actually a uint24_t
+ * primaryAdvIntervalMax - maximum adv interval (in units of 0.625ms), actually a uint24_t
+ * primaryAdvChannelMap - channels to use: bitmask of HCI_ADV_CHAN_MAP_USE_*
+ * ownAddrType - own addr type: HCI_ADV_OWN_ADDR_TYPE_*
+ * peerAddrType - set to 1 if direct adv to random addr, else ignored
+ * peerMac - if direct adv, the mac address of target, else ignored
+ * filterPolicy - filter policy: HCI_ADV_FILTER_POL_*
+ * txPower - requested adv transmit power in dBm
+ * primaryAdvPhy - PHY to use for primary adv, one of HCI_LE_PHY_* (CANNOT be HCI_LE_PHY_2M)
+ * secondaryAdvMaxSkip - how many adv can be skipped for secondary adv
+ * secondaryAdvPhy - PHY to use for secondary adv one of HCI_LE_PHY_*
+ * advSid - the SID value to send in adv packets (0x00..0x0f)
+ * enableScanRequestNotif - do we want an event when we are scanned?
+ * evt - the event structure to stash the chip's relpy in
+ */
+HCI_SIMPLY_SYNC_READ(LeSetExtendedAdvParams, (uint8_t advSetHandle, uint16_t advSetProperties, uint32_t primaryAdvIntervalMin, uint32_t primaryAdvIntervalMax, uint8_t primaryAdvChannelMap, uint8_t ownAddrType, uint8_t peerAddrType, const uint8_t *peerMac, uint8_t filterPolicy, int8_t txPower, uint8_t primaryAdvPhy, uint8_t secondaryAdvMaxSkip, uint8_t secondaryAdvPhy, uint8_t advSid, bool enableScanRequestNotif, struct hciCmplLeSetExtendedAdvParams *evt), HCI_OGF_LE, HCI_CMD_LE_Set_Extended_Adv_Params )
+ REQUIRE_VERSION(HCI_VERSION_5_0);
+ REQUIRE_FEATURE(0, HCI_LMP_FTR_LE_SUPPORTED_CONTROLLER);
+ HCI_COPY_IN_U8(advSetHandle);
+ HCI_COPY_IN_U16(advSetProperties);
+ HCI_COPY_IN_U24(primaryAdvIntervalMin);
+ HCI_COPY_IN_U24(primaryAdvIntervalMax);
+ HCI_COPY_IN_U8(primaryAdvChannelMap);
+ HCI_COPY_IN_U8(ownAddrType);
+ HCI_COPY_IN_U8(peerAddrType);
+ HCI_COPY_IN_MAC(peerMac);
+ HCI_COPY_IN_U8(filterPolicy);
+ HCI_COPY_IN_U8(txPower);
+ HCI_COPY_IN_U8(primaryAdvPhy);
+ HCI_COPY_IN_U8(secondaryAdvMaxSkip);
+ HCI_COPY_IN_U8(secondaryAdvPhy);
+ HCI_COPY_IN_U8(advSid);
+ HCI_COPY_IN_BOOL(enableScanRequestNotif)
+HCI_SIMPLY_SYNC_END
+/*
+ * FUNCTION: hciLeSetExtendedAdvDataSync
+ * USE: set extended adv data (BT5)
+ * PARAMS: advSetHandle - the adv set handle
+ * operation - one of HCI_EXTD_ADV_DATA_OP_*
+ * fragmentPreference - may the chip choose to fragment data over the air? (merely a suggestion)
+ * advDataLen - number of bytes that follow
+ * advData - the data
+ */
+HCI_SIMPLY_SYNC_WRITE_VAR_LEN(LeSetExtendedAdvData, (uint8_t advSetHandle, uint8_t operation, bool fragmentPreference, uint8_t advDataLen, const uint8_t *advData), HCI_OGF_LE, HCI_CMD_LE_Set_Extended_Adv_Data, advDataLen)
+ REQUIRE_VERSION(HCI_VERSION_5_0);
+ REQUIRE_FEATURE(0, HCI_LMP_FTR_LE_SUPPORTED_CONTROLLER);
+ HCI_COPY_IN_U8(advSetHandle);
+ HCI_COPY_IN_U8(operation);
+ HCI_COPY_IN_BOOL(fragmentPreference);
+ HCI_COPY_IN_U8(advDataLen);
+ HCI_COPY_IN_VAR_LEN_DATA(advData, advDataLen);
+HCI_SIMPLY_SYNC_END
+
+
+/*
+ * FUNCTION: hciLeSetExtendedScanRspDataSync
+ * USE: set extended adv scan rsp data (BT5)
+ * PARAMS: advSetHandle - the adv set handle
+ * operation - one of HCI_EXTD_ADV_DATA_OP_*, but HCI_EXTD_ADV_DATA_OP_UNCHANGED is not allowed
+ * fragmentPreference - may the chip choose to fragment data over the air? (merely a suggestion)
+ * scanRspDataLen - number of bytes that follow
+ * scanRspData - the data
+ */
+HCI_SIMPLY_SYNC_WRITE_VAR_LEN(LeSetExtendedScanRspData, (uint8_t advSetHandle, uint8_t operation, bool fragmentPreference, uint8_t scanRspDataLen, const uint8_t *scanRspData), HCI_OGF_LE, HCI_CMD_LE_Set_Extended_Scan_Rsp_Data, scanRspDataLen)
+ REQUIRE_VERSION(HCI_VERSION_5_0);
+ REQUIRE_FEATURE(0, HCI_LMP_FTR_LE_SUPPORTED_CONTROLLER);
+ HCI_COPY_IN_U8(advSetHandle);
+ HCI_COPY_IN_U8(operation);
+ HCI_COPY_IN_BOOL(fragmentPreference);
+ HCI_COPY_IN_U8(scanRspDataLen);
+ HCI_COPY_IN_VAR_LEN_DATA(scanRspData, scanRspDataLen);
+HCI_SIMPLY_SYNC_END
+
+/*
+ * FUNCTION: hciLeSetExtendedAdvEnableSync
+ * USE: set extended adv on or off (BT5)
+ * PARAMS: enable - enable or disable this set?
+ * advSetHandle - the adv set handle
+ * duration - adv duration in units of 10ms, or 0 for forever
+ * maxExtdAdvEvts - max number of extended adv events, or 0 for forever
+ * NOTES: this is a limited version of what this command can do, but
+ * it is more convenient - this gives us control over just one
+ * set at a time, whcih is OK for us.
+ */
+HCI_SIMPLY_SYNC_WRITE(LeSetExtendedAdvEnable, (bool enable, uint8_t advSetHandle, uint16_t duration, uint8_t maxExtdAdvEvts), HCI_OGF_LE, HCI_CMD_LE_Set_Extended_Adv_Enable)
+ REQUIRE_VERSION(HCI_VERSION_5_0);
+ REQUIRE_FEATURE(0, HCI_LMP_FTR_LE_SUPPORTED_CONTROLLER);
+ HCI_COPY_IN_BOOL(enable);
+ utilSetLE8(&cmd->numSets, 1);
+ utilSetLE8(&cmd->sets[0].advSetHandle, advSetHandle);
+ utilSetLE16(&cmd->sets[0].duration, duration);
+ utilSetLE16(&cmd->sets[0].maxExtdAdvEvts, maxExtdAdvEvts);
+HCI_SIMPLY_SYNC_END
/*
* FUNCTION: hciLeLtkRequestReplySync