/*----------------------------------------------------------------------------* * NAME * Nvm_Write * * DESCRIPTION * Erases the NVM memory. * * RETURNS * Nothing * *----------------------------------------------------------------------------*/ extern void Nvm_Erase(void) { sys_status result; /* NvmErase automatically enables the NVM before erasing */ result = NvmErase(TRUE); /* Disable NVM after erasing */ Nvm_Disable(); /* If NvmErase fails, report panic */ if(sys_status_success != result) { ReportPanic(app_panic_nvm_erase); } }
/*----------------------------------------------------------------------------* * NAME * Nvm_Read * * DESCRIPTION * Read words from the NVM Store after preparing the NVM to be readable. * After the read operation, perform the actions necessary to save power * on NVM. * * Read words starting at the word offset, and store them in the supplied * buffer. * * PARAMETERS * buffer [out] Data read from NVM * length [in] Number of words of data to read * offset [in] Offset from which to start reading, in words * * RETURNS * Nothing *----------------------------------------------------------------------------*/ void Nvm_Read(uint16 *buffer, uint16 length, uint16 offset) { sys_status result; /* Read from NVM. Firmware re-enables the NVM if it is disabled */ result = NvmRead(buffer, length, offset); /* Disable NVM to save power after read operation */ Nvm_Disable(); /* Report panic if NVM read is not successful */ if(sys_status_success != result) { ReportPanic(app_panic_nvm_read); } }
/*----------------------------------------------------------------------------* * NAME * Nvm_Write * * DESCRIPTION * Write words to the NVM Store after preparing the NVM to be writable. * After the write operation, perform the actions necessary to save power * on NVM. * * Write words from the supplied buffer into the NVM Store, starting at the * word offset. * * PARAMETERS * buffer [in] Data to write to NVM * length [in] Number of words of data to write * offset [in] Offset from which to start writing, in words * * RETURNS * Nothing *----------------------------------------------------------------------------*/ void Nvm_Write(uint16 *buffer, uint16 length, uint16 offset) { sys_status result; /* Function status */ /* Write to NVM. Firmware re-enables the NVM if it is disabled */ result = NvmWrite(buffer, length, offset); /* Disable NVM to save power after write operation */ Nvm_Disable(); /* Report panic if NVM write is not successful */ if(sys_status_success != result) { ReportPanic(app_panic_nvm_write); } }
void Nvm_Write(uint16* buffer, uint16 length, uint16 offset) { sys_status result; /* If the NVM has been earlier disabled, firmware automatically enables * NVM before writing to it. */ result = NvmWrite(buffer, length, offset); /* Disable NVM to save power after write operation */ Nvm_Disable(); /* PIO2 usage has to be toggled between LED operation and driving the NVM. * So, after the power to EEPROM is disabled, configure PIO2 to Pair LED * back again. */ SetUpPairLED(); /* If NvmWrite was a success, return */ if(sys_status_success == result) { /* Write was successful. */ return; } #ifdef NVM_TYPE_FLASH else if(nvm_status_needs_erase == result) { /* The application already has a copy of NVM data in its variables, * so we can erase the NVM */ Nvm_Erase(); /* Write back the NVM data. * Please note that the following function writes data into NVM and * should not fail. */ WriteApplicationAndServiceDataToNVM(); } #endif /* NVM_TYPE_FLASH */ else { /* Irrecoverable error. Reset the chip. */ ReportPanic(app_panic_nvm_write); } }
void Nvm_Read(uint16* buffer, uint16 length, uint16 offset) { sys_status result; /* If the NVM has been earlier disabled, firmware automatically enables * NVM before reading from it. */ result = NvmRead(buffer, length, offset); /* Disable NVM to save power after read operation */ Nvm_Disable(); /* PIO2 usage has to be toggled between LED operation and driving the NVM. * So, after the power to EEPROM is disabled, configure PIO2 to Pair LED * back again. */ SetUpPairLED(); if(sys_status_success != result) { ReportPanic(app_panic_nvm_read); } }
extern void Nvm_Write(uint16* buffer, uint16 length, uint16 offset) { sys_status result; /* Write to NVM. Firmware re-enables the NVM if it is disabled */ result = NvmWrite(buffer, length, offset); /* Disable NVM to save power after write operation */ Nvm_Disable(); /* If NvmWrite was a success, return */ if(sys_status_success == result) { /* Write was successful. */ return; } #ifdef NVM_TYPE_FLASH else if(nvm_status_needs_erase == result) { /* The application already has a copy of NVM data in its variables, * so we can erase the NVM */ Nvm_Erase(); /* Write back the NVM data. * Please note that the following function writes data into NVM and * should not fail. */ WriteApplicationAndServiceDataToNVM(); } #endif /* NVM_TYPE_FLASH */ else { /* Irrecoverable error. Reset the chip. */ ReportPanic(app_panic_nvm_write); } }
/*----------------------------------------------------------------------------* * NAME * appBuzzerTimerHandler * * DESCRIPTION * This function is used to stop the Buzzer at the expiry of * timer. * * RETURNS * Nothing. * *----------------------------------------------------------------------------*/ static void appBuzzerTimerHandler(timer_id tid) { uint32 beep_timer = SHORT_BEEP_TIMER_VALUE; g_app_hw_data.buzzer_tid = TIMER_INVALID; switch(g_app_hw_data.beep_type) { case beep_short: /* FALLTHROUGH */ case beep_long: { g_app_hw_data.beep_type = beep_off; /* Disable buzzer */ PioEnablePWM(BUZZER_PWM_INDEX_0, FALSE); } break; case beep_twice: { if(g_app_hw_data.beep_count == 0) { /* First beep sounded. Start the silent gap*/ g_app_hw_data.beep_count = 1; /* Disable buzzer */ PioEnablePWM(BUZZER_PWM_INDEX_0, FALSE); /* Time gap between two beeps */ beep_timer = BEEP_GAP_TIMER_VALUE; } else if(g_app_hw_data.beep_count == 1) { g_app_hw_data.beep_count = 2; /* Enable buzzer */ PioEnablePWM(BUZZER_PWM_INDEX_0, TRUE); /* Start beep */ beep_timer = SHORT_BEEP_TIMER_VALUE; } else { /* Two beeps have been sounded. Stop buzzer now*/ g_app_hw_data.beep_count = 0; /* Disable buzzer */ PioEnablePWM(BUZZER_PWM_INDEX_0, FALSE); g_app_hw_data.beep_type = beep_off; } } break; case beep_thrice: { if(g_app_hw_data.beep_count == 0 || g_app_hw_data.beep_count == 2) { /* First beep sounded. Start the silent gap*/ g_app_hw_data.beep_count++; /* Disable buzzer */ PioEnablePWM(BUZZER_PWM_INDEX_0, FALSE); /* Time gap between two beeps */ beep_timer = BEEP_GAP_TIMER_VALUE; } else if(g_app_hw_data.beep_count == 1 || g_app_hw_data.beep_count == 3) { g_app_hw_data.beep_count++; /* Enable buzzer */ PioEnablePWM(BUZZER_PWM_INDEX_0, TRUE); beep_timer = SHORT_BEEP_TIMER_VALUE; } else { /* Two beeps have been sounded. Stop buzzer now*/ g_app_hw_data.beep_count = 0; /* Disable buzzer */ PioEnablePWM(BUZZER_PWM_INDEX_0, FALSE); g_app_hw_data.beep_type = beep_off; } } break; default: { /* No such beep type */ ReportPanic(app_panic_unexpected_beep_type); /* Though break statement will not be executed after panic but this * has been kept to avoid any confusion for default case. */ } break; } if(g_app_hw_data.beep_type != beep_off) { /* start the timer */ g_app_hw_data.buzzer_tid = TimerCreate(beep_timer, TRUE, appBuzzerTimerHandler); } }
/*----------------------------------------------------------------------------* * NAME * SoundBuzzer * * DESCRIPTION * Function for sounding beeps. * * RETURNS * Nothing. * *----------------------------------------------------------------------------*/ extern void SoundBuzzer(buzzer_beep_type beep_type) { #ifdef ENABLE_BUZZER uint32 beep_timer = SHORT_BEEP_TIMER_VALUE; PioEnablePWM(BUZZER_PWM_INDEX_0, FALSE); TimerDelete(g_app_hw_data.buzzer_tid); g_app_hw_data.buzzer_tid = TIMER_INVALID; g_app_hw_data.beep_count = 0; /* Store the beep type in some global variable. It will used on timer expiry * to check the type of beeps being sounded. */ g_app_hw_data.beep_type = beep_type; switch(g_app_hw_data.beep_type) { case beep_off: { /* Don't do anything */ } break; case beep_short: /* FALLTHROUGH */ case beep_twice: /* Two short beeps will be sounded */ /* FALLTHROUGH */ case beep_thrice: /* Three short beeps will be sounded */ { /* One short beep will be sounded */ beep_timer = SHORT_BEEP_TIMER_VALUE; } break; case beep_long: { /* One long beep will be sounded */ beep_timer = LONG_BEEP_TIMER_VALUE; } break; break; default: { /* No such beep type defined */ ReportPanic(app_panic_unexpected_beep_type); /* Though break statement will not be executed after panic but this * has been kept to avoid any confusion for default case. */ } break; } if(g_app_hw_data.beep_type != beep_off) { /* Initialize beep count to zero */ g_app_hw_data.beep_count = 0; /* Enable buzzer */ PioEnablePWM(BUZZER_PWM_INDEX_0, TRUE); TimerDelete(g_app_hw_data.buzzer_tid); g_app_hw_data.buzzer_tid = TimerCreate(beep_timer, TRUE, appBuzzerTimerHandler); } #endif /* ENABLE_BUZZER */ }
/*----------------------------------------------------------------------------* * NAME * SoundBuzzer * * DESCRIPTION * This function is called to trigger beeps of different types, enumerated * by 'buzzer_beep_type'. * * PARAMETERS * beep_type [in] Type of beep required * * RETURNS * Nothing *----------------------------------------------------------------------------*/ extern void SoundBuzzer(buzzer_beep_type beep_type) { /* Duration of beep */ uint32 beep_timer = SHORT_BEEP_TIMER_VALUE; /* Disable the buzzer and stop the buzzer timer. */ PioEnablePWM(BUZZER_PWM_INDEX_0, FALSE); if (g_buzz_data.buzzer_tid != TIMER_INVALID) { TimerDelete(g_buzz_data.buzzer_tid); g_buzz_data.buzzer_tid = TIMER_INVALID; } /* Reset the beeper state */ g_buzz_data.beep_count = 0; /* Store the beep type. It will be used on timer expiry to check the type of * beep being sounded. */ g_buzz_data.beep_type = beep_type; switch(g_buzz_data.beep_type) { case buzzer_beep_off: { /* Don't do anything */ } break; case buzzer_beep_short: /* One short beep will be sounded */ /* FALLTHROUGH */ case buzzer_beep_twice: /* Two short beeps will be sounded */ /* FALLTHROUGH */ case buzzer_beep_thrice: /* Three short beeps will be sounded */ { beep_timer = SHORT_BEEP_TIMER_VALUE; } break; case buzzer_beep_long: { /* One long beep will be sounded */ beep_timer = LONG_BEEP_TIMER_VALUE; } break; default: { /* No such beep type defined */ ReportPanic(app_panic_unexpected_beep_type); } break; } if(g_buzz_data.beep_type != buzzer_beep_off) { /* Enable buzzer */ PioEnablePWM(BUZZER_PWM_INDEX_0, TRUE); /* Start the buzzer timer */ g_buzz_data.buzzer_tid = TimerCreate(beep_timer, TRUE, appBuzzerTimerHandler); } }
/*----------------------------------------------------------------------------* * NAME * appBuzzerTimerHandler * * DESCRIPTION * This function is used to stop the Buzzer at the expiry of timer. * * PARAMETERS * tid [in] ID of expired timer (unused) * * RETURNS * Nothing *----------------------------------------------------------------------------*/ static void appBuzzerTimerHandler(timer_id tid) { /* Duration of next timer */ uint32 beep_timer = SHORT_BEEP_TIMER_VALUE; /* The buzzer timer has just expired, so reset the timer ID */ g_buzz_data.buzzer_tid = TIMER_INVALID; switch(g_buzz_data.beep_type) { case buzzer_beep_short: /* FALLTHROUGH */ case buzzer_beep_long: { g_buzz_data.beep_type = buzzer_beep_off; /* Disable buzzer */ PioEnablePWM(BUZZER_PWM_INDEX_0, FALSE); } break; case buzzer_beep_twice: { if(g_buzz_data.beep_count == 0) { /* First beep sounded. Increment the beep count and start the * silent gap. */ g_buzz_data.beep_count = 1; /* Disable buzzer */ PioEnablePWM(BUZZER_PWM_INDEX_0, FALSE); /* Time gap between two beeps */ beep_timer = BEEP_GAP_TIMER_VALUE; } else if(g_buzz_data.beep_count == 1) { /* Sound the second beep and increment the beep count. */ g_buzz_data.beep_count = 2; /* Enable buzzer */ PioEnablePWM(BUZZER_PWM_INDEX_0, TRUE); /* Start another short beep */ beep_timer = SHORT_BEEP_TIMER_VALUE; } else { /* Two beeps have been sounded. Stop buzzer now and reset the * beep count. */ g_buzz_data.beep_count = 0; /* Disable buzzer */ PioEnablePWM(BUZZER_PWM_INDEX_0, FALSE); g_buzz_data.beep_type = buzzer_beep_off; } } break; case buzzer_beep_thrice: { if(g_buzz_data.beep_count == 0 || g_buzz_data.beep_count == 2) { /* Start the silent gap*/ ++g_buzz_data.beep_count; /* Disable buzzer */ PioEnablePWM(BUZZER_PWM_INDEX_0, FALSE); /* Time gap between two beeps */ beep_timer = BEEP_GAP_TIMER_VALUE; } else if(g_buzz_data.beep_count == 1 || g_buzz_data.beep_count == 3) { /* Start the beep sounding part. */ ++g_buzz_data.beep_count; /* Enable buzzer */ PioEnablePWM(BUZZER_PWM_INDEX_0, TRUE); beep_timer = SHORT_BEEP_TIMER_VALUE; } else { /* Three beeps have been sounded. Stop the buzzer. */ g_buzz_data.beep_count = 0; /* Disable buzzer */ PioEnablePWM(BUZZER_PWM_INDEX_0, FALSE); g_buzz_data.beep_type = buzzer_beep_off; } } break; default: { /* No such beep type */ ReportPanic(app_panic_unexpected_beep_type); } break; } if(g_buzz_data.beep_type != buzzer_beep_off) { /* Start the timer */ g_buzz_data.buzzer_tid = TimerCreate(beep_timer, TRUE, appBuzzerTimerHandler); } }
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 * * RETURNS * Nothing. * *---------------------------------------------------------------------------*/ static void gattSetAdvertParams(bool fast_connection) { uint8 advert_data[MAX_ADV_DATA_LEN]; uint16 length; 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_UNKNOWN_VALUE), LE8_H(APPEARANCE_UNKNOWN_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; /* 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 (CsrMeshStoreUserAdvData(length, advert_data, ad_src_advertise) != TRUE) { 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 (CsrMeshStoreUserAdvData(ATTR_LEN_DEVICE_APPEARANCE + 1, device_appearance, ad_src_advertise) != TRUE) { 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 (CsrMeshStoreUserAdvData(TX_POWER_VALUE_LENGTH, device_tx_power, ad_src_advertise) != TRUE) { ReportPanic(app_panic_set_advert_data); } addDeviceNameToAdvData(length_added_to_adv, 0); }
/*----------------------------------------------------------------------------* * 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); }
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); }