/*----------------------------------------------------------------------------* * NAME * startBeaconing * * DESCRIPTION * This function is called to start beacon advertisements * * RETURNS * Nothing. * *---------------------------------------------------------------------------*/ void startBeaconing(void) { uint8 advData[BEACON_ADVERT_SIZE]; uint16 offset = 0; /* set the GAP Broadcaster role */ GapSetMode(gap_role_broadcaster, gap_mode_discover_no, gap_mode_connect_no, gap_mode_bond_no, gap_mode_security_none); /* clear the existing advertisement data */ LsStoreAdvScanData(0, NULL, ad_src_advertise); /* set the advertisement interval */ GapSetAdvInterval(BEACON_ADVERTISING_INTERVAL_MIN, BEACON_ADVERTISING_INTERVAL_MAX); /* store the manufacturing data */ advData[offset++] = AD_TYPE_MANUF; /* Apple company code, little endian */ advData[offset++] = 0x4C; advData[offset++] = 0x00; advData[offset++] = 2; /* Magic number */ advData[offset++] = 0x15; /* Length of the beacon payload */ /* Beacon UUID */ MemCopy(advData + offset, g_app_data.uuid, sizeof(g_app_data.uuid)); offset += sizeof(g_app_data.uuid); /* Beacon major */ advData[offset++] = WORD_MSB(g_app_data.major); advData[offset++] = WORD_LSB(g_app_data.major); /* Beacon minor */ advData[offset++] = WORD_MSB(g_app_data.minor); advData[offset++] = WORD_LSB(g_app_data.minor); /* Beacon TX Power */ advData[offset++] = g_app_data.txPower; /* store the advertisement data */ LsStoreAdvScanData(BEACON_ADVERT_SIZE, advData, ad_src_advertise); /* Start broadcasting */ LsStartStopAdvertise(TRUE, whitelist_disabled, ls_addr_type_random); }
/*----------------------------------------------------------------------------* * NAME * startAdvertising * * DESCRIPTION * This function is called to start advertisements. * * Advertisement packet will contain Flags AD and Manufacturer-specific * AD with Manufacturer id set to CSR and payload set to the value of * the User Key 0. The payload size is set by the User Key 1. * * +--------+-------------------------------------------------+ * |FLAGS AD|MANUFACTURER AD | * +--------+-------------------------------------------------+ * 0 2 3 * * RETURNS * Nothing. * *---------------------------------------------------------------------------*/ static void BeaconInit(void) { uint8 filler; uint16 advInterval; uint8 advPayloadSize; ls_addr_type addressType = ls_addr_type_public; /* use public address */ /* initialise values from User CsKeys */ /* read User key 0 for the payload filler */ filler = (uint8)(CSReadUserKey(0) & 0x00FF); /* read User key 1 for the payload size */ advPayloadSize = (uint8)(CSReadUserKey(1) & 0x00FF); /* range check */ if((advPayloadSize < 1) || (advPayloadSize > MAX_ADVERT_PAYLOAD_SIZE)) { /* revert to default payload size */ advPayloadSize = DEFAULT_ADVERT_PAYLOAD_SIZE; } /* read User key 2 for the advertising interval */ advInterval = CSReadUserKey(2); /* range check */ if((advInterval < MIN_ADVERTISING_INTERVAL) || (advInterval > MAX_ADVERTISING_INTERVAL)) { /* revert to default advertising interval */ advInterval = DEFAULT_ADVERTISING_INTERVAL; } /* read address type from User key 3 */ if(CSReadUserKey(3)) { /* use random address type */ addressType = ls_addr_type_random; /* generate and set the random address */ appSetRandomAddress(); } /* set the GAP Broadcaster role */ GapSetMode(gap_role_broadcaster, gap_mode_discover_no, gap_mode_connect_no, gap_mode_bond_no, gap_mode_security_none); /* clear the existing advertisement data, if any */ LsStoreAdvScanData(0, NULL, ad_src_advertise); /* set the advertisement interval, API accepts the value in microseconds */ GapSetAdvInterval(advInterval * MILLISECOND, advInterval * MILLISECOND); }
static void gattSetAdvertParams(bool fast_connection, gap_mode_connect connect_mode) { uint8 advert_data[MAX_ADV_DATA_LEN]; uint16 length; uint32 adv_interval_min = RP_ADVERTISING_INTERVAL_MIN; uint32 adv_interval_max = RP_ADVERTISING_INTERVAL_MAX; int8 tx_power_level; /* Unsigned value */ gap_mode_discover discover_mode = gap_mode_discover_limited; TYPED_BD_ADDR_T temp_addr; /* A variable to keep track of the data added to AdvData. The limit is * MAX_ADV_DATA_LEN. GAP layer will add AD Flags to AdvData which is 3 * bytes. Refer BT Spec 4.0, Vol 3, Part C, Sec 11.1.3. */ uint16 length_added_to_adv = 3; uint16 length_added_to_scan = 0; /* Tx power level value prefixed with 'Tx Power' AD Type */ uint8 device_tx_power[TX_POWER_VALUE_LENGTH] = { AD_TYPE_TX_POWER}; uint8 device_appearance[ATTR_LEN_DEVICE_APPEARANCE + 1] = { AD_TYPE_APPEARANCE, LE8_L(APPEARANCE_GENERAL_HID_VALUE), LE8_H(APPEARANCE_GENERAL_HID_VALUE) }; /* If privacy is enabled, reconnection address will be used as Initiator's * address for directed advertisements. Otherwise, the bonded host address * shall be used as Initiator's address. */ #ifdef __GAP_PRIVACY_SUPPORT__ temp_addr.type = ls_addr_type_random; MemCopy(&temp_addr.addr, GapGetReconnectionAddress(), sizeof(BD_ADDR_T)); #else /* __GAP_PRIVACY_SUPPORT__ */ temp_addr.type = ls_addr_type_public; MemCopy(&temp_addr.addr, &g_btcar_data.bonded_bd_addr.addr, sizeof(BD_ADDR_T)); #endif /* ! __GAP_PRIVACY_SUPPORT__ */ if(fast_connection) { adv_interval_min = FC_ADVERTISING_INTERVAL_MIN; adv_interval_max = FC_ADVERTISING_INTERVAL_MAX; } if(g_btcar_data.bonded) { /* As the device is bonded, we don't want it to be discoverable any * more */ discover_mode = gap_mode_discover_no; } if((GapSetMode(gap_role_peripheral, discover_mode, connect_mode, gap_mode_bond_yes, gap_mode_security_unauthenticate) != ls_err_none) || (connect_mode == gap_mode_connect_directed && GapSetAdvAddress(&temp_addr) != ls_err_none) || /* Advertisement interval will be ignored for directed advertisement */ (GapSetAdvInterval(adv_interval_min, adv_interval_max) != ls_err_none)) { ReportPanic(app_panic_set_advert_params); return; } /* Reset existing advertising data as application is again going to add * data for undirected advertisements. */ if(LsStoreAdvScanData(0, NULL, ad_src_advertise) != ls_err_none) { ReportPanic(app_panic_set_advert_data); return; } /* Reset existing scan response data as application is again going to add * data for undirected advertisements. */ if(LsStoreAdvScanData(0, NULL, ad_src_scan_rsp) != ls_err_none) { ReportPanic(app_panic_set_scan_rsp_data); return; } /* Add to advData only if undirected advertisements are to be done. */ if(connect_mode == gap_mode_connect_undirected) { /* Set up the advertising data. The GAP layer will automatically add the * AD Flags field so all we need to do here is add 16-bit supported * services UUID and Complete Local Name type. Applications are free to * add any other AD types based upon the profile requirements and * subject to the maximum AD size of 31 octets. */ /* Add 16-bit UUID list of the services supported by the device */ length = GetSupported16BitUUIDServiceList(advert_data); /* Before adding data to the ADV_IND, increment 'lengthAddedToAdv' to * keep track of the total number of bytes added to ADV_IND. At the end * while adding the device name to the ADV_IND, this can be used to * verify whether the complete name can fit into the AdvData adhering to * the limit of 31 octets. In addition to the above populated fields, a * 'length' field will also be added to AdvData by GAP layer. Refer * BT 4.0 spec, Vol 3, Part C, Figure 11.1. */ length_added_to_adv += (length + 1); if (LsStoreAdvScanData(length, advert_data, ad_src_advertise) != ls_err_none) { ReportPanic(app_panic_set_advert_data); return; } length_added_to_adv += (sizeof(device_appearance) + 1); /* Add device appearance as advertisement data */ if (LsStoreAdvScanData(sizeof(device_appearance), device_appearance, ad_src_advertise) != ls_err_none) { ReportPanic(app_panic_set_advert_data); return; } /* If 128-bit proprietary service UUID is added to the advData, there * will be no space left for any more data. So don't add the * TxPowerLevel to the advData. */ /* Read tx power of the chip */ if(LsReadTransmitPowerLevel(&tx_power_level) != ls_err_none) { /* Readin tx power failed */ ReportPanic(app_panic_read_tx_pwr_level); } /* Add the read tx power level to g_device_tx_power * Tx power level value is of 1 byte */ device_tx_power[TX_POWER_VALUE_LENGTH - 1] = (uint8 )tx_power_level; length_added_to_scan += TX_POWER_VALUE_LENGTH + 1; /* Add tx power value of device to the scan response data */ if (LsStoreAdvScanData(TX_POWER_VALUE_LENGTH, device_tx_power, ad_src_scan_rsp) != ls_err_none) { ReportPanic(app_panic_set_scan_rsp_data); return; } addDeviceNameToAdvData(length_added_to_adv, length_added_to_scan); } }
static void addDeviceNameToAdvData(uint16 adv_data_len, uint16 scan_data_len) { uint8 *p_device_name = NULL; uint16 device_name_adtype_len; /* Read device name along with AD Type and its length */ p_device_name = GapGetNameAndLength(&device_name_adtype_len); /* Increment device_name_length by one to account for length field * which will be added by the GAP layer. */ /* Check if Complete Device Name can fit in remaining advData space */ if((device_name_adtype_len + 1) <= (MAX_ADV_DATA_LEN - adv_data_len)) { /* Add complete device name to Advertisement data */ p_device_name[0] = AD_TYPE_LOCAL_NAME_COMPLETE; /* Add Complete Device Name to Advertisement Data */ if (LsStoreAdvScanData(device_name_adtype_len , p_device_name, ad_src_advertise) != ls_err_none) { ReportPanic(app_panic_set_advert_data); return; } } /* Check if Complete Device Name can fit in Scan response message */ else if((device_name_adtype_len + 1) <= (MAX_ADV_DATA_LEN - scan_data_len)) { /* Add complete device name to scan response data */ p_device_name[0] = AD_TYPE_LOCAL_NAME_COMPLETE; /* Add Complete Device Name to Scan Response Data */ if (LsStoreAdvScanData(device_name_adtype_len , p_device_name, ad_src_scan_rsp) != ls_err_none) { ReportPanic(app_panic_set_scan_rsp_data); return; } } /* Check if Shortened Device Name can fit in remaining advData space */ else if((MAX_ADV_DATA_LEN - adv_data_len) >= (SHORTENED_DEV_NAME_LEN + 2)) /* Added 2 for Length and AD type * added by GAP layer */ { /* Add shortened device name to Advertisement data */ p_device_name[0] = AD_TYPE_LOCAL_NAME_SHORT; if (LsStoreAdvScanData(SHORTENED_DEV_NAME_LEN , p_device_name, ad_src_advertise) != ls_err_none) { ReportPanic(app_panic_set_advert_data); return; } } else /* Add device name to remaining Scan reponse data space */ { /* Add as much as can be stored in Scan Response data */ p_device_name[0] = AD_TYPE_LOCAL_NAME_SHORT; if (LsStoreAdvScanData(MAX_ADV_DATA_LEN - scan_data_len, p_device_name, ad_src_scan_rsp) != ls_err_none) { ReportPanic(app_panic_set_scan_rsp_data); return; } } }
/*----------------------------------------------------------------------------* * NAME * gattSetAdvertParams * * DESCRIPTION * This function is used to set advertisement parameters. * * PARAMETERS * p_addr [in] Bonded host address * fast_connection [in] TRUE: Fast advertisements * FALSE: Slow advertisements * * RETURNS * Nothing *----------------------------------------------------------------------------*/ static void gattSetAdvertParams(TYPED_BD_ADDR_T *p_addr, bool fast_connection) { uint8 advert_data[MAX_ADV_DATA_LEN];/* Advertisement packet */ uint16 length; /* Length of advertisement packet */ /* Advertisement interval, microseconds */ uint32 adv_interval_min; uint32 adv_interval_max; /* Tx power level value prefixed with 'Tx Power' AD Type */ /* Refer to BT4.0 specification, Vol3-part-C-Section-11.1.5 */ uint8 device_tx_power[TX_POWER_VALUE_LENGTH] = { AD_TYPE_TX_POWER }; /* Device appearance */ uint8 device_appearance[ATTR_LEN_DEVICE_APPEARANCE + 1] = { AD_TYPE_APPEARANCE, WORD_LSB(APPEARANCE_APPLICATION_VALUE), WORD_MSB(APPEARANCE_APPLICATION_VALUE) }; /* A variable to keep track of the data added to advert_data. The limit is * MAX_ADV_DATA_LEN. GAP layer will add AD Flags to advert_data which is 3 * bytes. Refer BT Spec 4.0, Vol 3, Part C, Sec 11.1.3: * * First byte is length * second byte is AD TYPE = 0x1 * Third byte is Flags description */ uint16 length_added_to_adv = 3; if(fast_connection) { adv_interval_min = FC_ADVERTISING_INTERVAL_MIN; adv_interval_max = FC_ADVERTISING_INTERVAL_MAX; } if((GapSetMode(gap_role_peripheral, gap_mode_discover_general, gap_mode_connect_undirected, gap_mode_bond_yes, gap_mode_security_unauthenticate) != ls_err_none) || (GapSetAdvInterval(adv_interval_min, adv_interval_max) != ls_err_none)) { ReportPanic(app_panic_set_advert_params); } /* Add bonded device to white list.*/ if(IsWhiteListEnabled()) { /* Initial case when advertisements are started for Bonded host for * 10 seconds. White list is configured with the Bonded host address */ if(LsAddWhiteListDevice(p_addr)!= ls_err_none) { ReportPanic(app_panic_add_whitelist); } } /* Reset existing advertising data */ if(LsStoreAdvScanData(0, NULL, ad_src_advertise) != ls_err_none) { ReportPanic(app_panic_set_advert_data); } /* Reset existing scan response data */ if(LsStoreAdvScanData(0, NULL, ad_src_scan_rsp) != ls_err_none) { ReportPanic(app_panic_set_scan_rsp_data); } /* Setup ADVERTISEMENT DATA */ /* Add UUID list of the services supported by the device */ length = GetSupportedUUIDServiceList(advert_data); /* One added for Length field, which will be added to Adv Data by GAP * layer */ length_added_to_adv += (length + 1); if (LsStoreAdvScanData(length, advert_data, ad_src_advertise) != ls_err_none) { ReportPanic(app_panic_set_advert_data); } /* One added for Length field, which will be added to Adv Data by GAP * layer */ length_added_to_adv += (sizeof(device_appearance) + 1); /* Add device appearance to the advertisements */ if (LsStoreAdvScanData(ATTR_LEN_DEVICE_APPEARANCE + 1, device_appearance, ad_src_advertise) != ls_err_none) { ReportPanic(app_panic_set_advert_data); } /* Change the Radio and Adv tx params for CONFIG mode */ /* Update the radio tx power level here */ LsSetTransmitPowerLevel(RADIO_TX_POWER_CONFIG); /* Update the adv tx power level here */ device_tx_power[TX_POWER_VALUE_LENGTH - 1] = ADV_TX_POWER_CONFIG; /* NOTE: The 2 tx params above are reset to the tx_power_mode on disconnection */ /* One added for Length field, it will be added to Adv Data by GAP layer */ length_added_to_adv += (TX_POWER_VALUE_LENGTH + 1); /* Add tx power value of device to the advertising data */ if (LsStoreAdvScanData(TX_POWER_VALUE_LENGTH, device_tx_power, ad_src_advertise) != ls_err_none) { ReportPanic(app_panic_set_advert_data); } addDeviceNameToAdvData(length_added_to_adv, 0); }
/*----------------------------------------------------------------------------* * NAME * startAdvertising * * DESCRIPTION * This function is called to start advertisements. * * Advertisement packet will contain Flags AD and Manufacturer-specific * AD with Manufacturer id set to CSR and payload set to the value of * the User Key 0. The payload size is set by the User Key 1. * * +--------+-------------------------------------------------+ * |FLAGS AD|MANUFACTURER AD | * +--------+-------------------------------------------------+ * 0 2 3 * * RETURNS * Nothing. * *---------------------------------------------------------------------------*/ void startAdvertising(void) { uint8 advData[MAX_ADVERT_PACKET_SIZE]; uint16 offset = 0; uint8 filler; uint16 advInterval; uint8 advPayloadSize; ls_addr_type addressType = ls_addr_type_public; /* use public address */ /* initialise values from User CsKeys */ /* read User key 0 for the payload filler */ filler = (uint8)(CSReadUserKey(0) & 0x00FF); /* read User key 1 for the payload size */ advPayloadSize = (uint8)(CSReadUserKey(1) & 0x00FF); /* range check */ if((advPayloadSize < 1) || (advPayloadSize > MAX_ADVERT_PAYLOAD_SIZE)) { /* revert to default payload size */ advPayloadSize = DEFAULT_ADVERT_PAYLOAD_SIZE; } /* read User key 2 for the advertising interval */ advInterval = CSReadUserKey(2); /* range check */ if((advInterval < MIN_ADVERTISING_INTERVAL) || (advInterval > MAX_ADVERTISING_INTERVAL)) { /* revert to default advertising interval */ advInterval = DEFAULT_ADVERTISING_INTERVAL; } /* read address type from User key 3 */ if(CSReadUserKey(3)) { /* use random address type */ addressType = ls_addr_type_random; /* generate and set the random address */ appSetRandomAddress(); } /* set the GAP Broadcaster role */ GapSetMode(gap_role_broadcaster, gap_mode_discover_no, gap_mode_connect_no, gap_mode_bond_no, gap_mode_security_none); /* clear the existing advertisement data, if any */ LsStoreAdvScanData(0, NULL, ad_src_advertise); /* set the advertisement interval, API accepts the value in microseconds */ GapSetAdvInterval(advInterval * MILLISECOND, advInterval * MILLISECOND); /* manufacturer-specific data */ advData[0] = AD_TYPE_MANUF; /* CSR company code, little endian */ advData[1] = 0x0A; advData[2] = 0x00; /* fill in the rest of the advertisement */ for(offset = 0; offset < advPayloadSize; offset++) { advData[3 + offset] = filler; } /* store the advertisement data */ LsStoreAdvScanData(advPayloadSize + 3, advData, ad_src_advertise); /* Start broadcasting */ LsStartStopAdvertise(TRUE, whitelist_disabled, addressType); }
static void gattSetAdvertParams(bool fast_connection) { uint8 advert_data[MAX_ADV_DATA_LEN]; uint16 length; uint32 adv_interval_min = RP_ADVERTISING_INTERVAL_MIN; uint32 adv_interval_max = RP_ADVERTISING_INTERVAL_MAX; int8 tx_power_level = 0xff; /* Signed value */ /* Tx power level value prefixed with 'Tx Power' AD Type */ uint8 device_tx_power[TX_POWER_VALUE_LENGTH] = { AD_TYPE_TX_POWER }; uint8 device_appearance[ATTR_LEN_DEVICE_APPEARANCE + 1] = { AD_TYPE_APPEARANCE, LE8_L(APPEARANCE_HR_SENSOR_VALUE), LE8_H(APPEARANCE_HR_SENSOR_VALUE) }; /* A variable to keep track of the data added to AdvData. The limit is * MAX_ADV_DATA_LEN. GAP layer will add AD Flags to AdvData which * is 3 bytes. Refer BT Spec 4.0, Vol 3, Part C, Sec 11.1.3. */ uint16 length_added_to_adv = 3; if(fast_connection) { adv_interval_min = FC_ADVERTISING_INTERVAL_MIN; adv_interval_max = FC_ADVERTISING_INTERVAL_MAX; } /* In a Public Environment like Gym, there is a requirement for HR Sensor * to communicate with fitness machines even without having a bond. So, * for HR Sensor application we will not enforce bonding by calling SM * Slave Security Request. Though, we will set HR Sensor's security * capabilities to 'gap_mode_bond_yes' so that we accept bonding if the * collector (like Watch or Cell Phone) would like to bond. */ if((GapSetMode(gap_role_peripheral, gap_mode_discover_general, gap_mode_connect_undirected, gap_mode_bond_yes, gap_mode_security_unauthenticate) != ls_err_none) || (GapSetAdvInterval(adv_interval_min, adv_interval_max) != ls_err_none)) { ReportPanic(app_panic_set_advert_params); } /* Add bonded device to white list.*/ if((g_hr_data.enable_white_list == TRUE)) { /* Initial case when advertisements are started for Bonded host for * 10 seconds. White list is configured with the Bonded host address */ if(LsAddWhiteListDevice(&g_hr_data.bonded_bd_addr)!= ls_err_none) { ReportPanic(app_panic_add_whitelist); } } /* Reset existing advertising data */ if(LsStoreAdvScanData(0, NULL, ad_src_advertise) != ls_err_none) { ReportPanic(app_panic_set_advert_data); } /* Reset existing scan response data */ if(LsStoreAdvScanData(0, NULL, ad_src_scan_rsp) != ls_err_none) { ReportPanic(app_panic_set_scan_rsp_data); } /* Setup ADVERTISEMENT DATA */ /* Add UUID list of the services supported by the device */ length = GetSupported16BitUUIDServiceList(advert_data); /* One added for Length field, which will be added to Adv Data by GAP * layer */ length_added_to_adv += (length + 1); if (LsStoreAdvScanData(length, advert_data, ad_src_advertise) != ls_err_none) { ReportPanic(app_panic_set_advert_data); } /* One added for Length field, which will be added to Adv Data by GAP * layer */ length_added_to_adv += (sizeof(device_appearance) + 1); /* Add device appearance to the advertisements */ if (LsStoreAdvScanData(ATTR_LEN_DEVICE_APPEARANCE + 1, device_appearance, ad_src_advertise) != ls_err_none) { ReportPanic(app_panic_set_advert_data); } /* Read tx power of the chip */ if(LsReadTransmitPowerLevel(&tx_power_level) != ls_err_none) { /* Reading tx power failed */ ReportPanic(app_panic_read_tx_pwr_level); } /* Add the read tx power level to device_tx_power * Tx power level value is of 1 byte */ device_tx_power[TX_POWER_VALUE_LENGTH - 1] = (uint8 )tx_power_level; /* One added for Length field, which will be added to Adv Data by GAP * layer */ length_added_to_adv += (TX_POWER_VALUE_LENGTH + 1); /* Add tx power value of device to the advertising data */ if (LsStoreAdvScanData(TX_POWER_VALUE_LENGTH, device_tx_power, ad_src_advertise) != ls_err_none) { ReportPanic(app_panic_set_advert_data); } addDeviceNameToAdvData(length_added_to_adv, 0); }