/**@brief Function for executing the state entry action. */ static __INLINE void state_entry_action_execute(void) { spi_slave_evt_t event; switch (m_spi_state) { case SPI_BUFFER_RESOURCE_REQUESTED: NRF_SPIS1->TASKS_ACQUIRE = 1u; break; case SPI_BUFFER_RESOURCE_CONFIGURED: event.evt_type = SPI_SLAVE_BUFFERS_SET_DONE; event.rx_amount = 0; event.tx_amount = 0; APP_ERROR_CHECK_BOOL(m_event_callback != NULL); m_event_callback(event); break; case SPI_XFER_COMPLETED: event.evt_type = SPI_SLAVE_XFER_DONE; event.rx_amount = NRF_SPIS1->AMOUNTRX; event.tx_amount = NRF_SPIS1->AMOUNTTX; APP_ERROR_CHECK_BOOL(m_event_callback != NULL); m_event_callback(event); break; default: // No implementation required. break; } }
/**@brief Function for application main entry. */ int main(void) { gpio_config(); bool success = nrf6350_lcd_init(); APP_ERROR_CHECK_BOOL(success); success = nrf6350_lcd_write_string(" BLE ANCS ", MAX_CHARACTERS_PER_LINE, LCD_UPPER_LINE, 0); APP_ERROR_CHECK_BOOL(success); // Initialize. leds_init(); timers_init(); gpiote_init(); buttons_init(); ble_stack_init(); bond_manager_init(); gap_params_init(); service_add(); advertising_init(); conn_params_init(); sec_params_init(); radio_notification_init(); // Start execution. advertising_start(); // Enter main loop. for (;;) { power_manage(); } }
/**@brief Function for executing the state entry action. */ static void spis_state_entry_action_execute(NRF_SPIS_Type * p_spis, spis_cb_t * p_cb) { nrf_drv_spis_event_t event; switch (p_cb->spi_state) { case SPIS_BUFFER_RESOURCE_REQUESTED: nrf_spis_task_trigger(p_spis, NRF_SPIS_TASK_ACQUIRE); break; case SPIS_BUFFER_RESOURCE_CONFIGURED: event.evt_type = NRF_DRV_SPIS_BUFFERS_SET_DONE; event.rx_amount = 0; event.tx_amount = 0; APP_ERROR_CHECK_BOOL(p_cb->handler != NULL); p_cb->handler(event); break; case SPIS_XFER_COMPLETED: event.evt_type = NRF_DRV_SPIS_XFER_DONE; event.rx_amount = nrf_spis_rx_amount_get(p_spis); event.tx_amount = nrf_spis_tx_amount_get(p_spis); APP_ERROR_CHECK_BOOL(p_cb->handler != NULL); p_cb->handler(event); break; default: // No implementation required. break; } }
/**@brief Function for releasing TX or RX buffer. */ static __INLINE void spi_master_buffer_release(uint8_t * * const pp_buf, uint16_t * const p_buf_len) { APP_ERROR_CHECK_BOOL(pp_buf != NULL); APP_ERROR_CHECK_BOOL(p_buf_len != NULL); *pp_buf = NULL; *p_buf_len = 0; }
/**@brief Function for bootloader main entry. */ int main(void) { uint32_t err_code; bool dfu_start = false; bool app_reset = (NRF_POWER->GPREGRET == BOOTLOADER_DFU_START); // This check ensures that the defined fields in the bootloader corresponds with actual // setting in the nRF51 chip. APP_ERROR_CHECK_BOOL(*((uint32_t *)NRF_UICR_BOOT_START_ADDRESS) == BOOTLOADER_REGION_START); APP_ERROR_CHECK_BOOL(NRF_FICR->CODEPAGESIZE == CODE_PAGE_SIZE); // Initialize. timers_init(); gpiote_init(); buttons_init(); bootloader_init(); // Check if we reset in the middle of a firmware update if (bootloader_dfu_sd_in_progress()) { err_code = bootloader_dfu_sd_update_continue(); APP_ERROR_CHECK(err_code); softdevice_init(!app_reset); scheduler_init(); err_code = bootloader_dfu_sd_update_finalize(); APP_ERROR_CHECK(err_code); } else { // If stack is present then continue initialization of bootloader. softdevice_init(!app_reset); scheduler_init(); } // Check if the Bootloader Control pin is low. If so, enter the bootloader // mode. dfu_start = (nrf_gpio_pin_read(BOOTLOADER_CTRL_PIN) == 0); // If the Bootloader Control pin is low or the application in the flash // is not valid, enter the bootloader mode. if (dfu_start || (!bootloader_app_is_valid(DFU_BANK_0_REGION_START))) { err_code = sd_power_gpregret_clr(POWER_GPREGRET_GPREGRET_Msk); APP_ERROR_CHECK(err_code); // Initiate an update of the firmware. err_code = bootloader_dfu_start(); APP_ERROR_CHECK(err_code); } // If the application was or now is valid, run it if (bootloader_app_is_valid(DFU_BANK_0_REGION_START)) { // Select a bank region to use as application region. // @note: Only applications running from DFU_BANK_0_REGION_START is supported. bootloader_app_start(DFU_BANK_0_REGION_START); } NVIC_SystemReset(); }
static uint32_t indication_char_add(uint16_t uuid, uint8_t *p_char_value, uint16_t char_len, const ble_srv_cccd_security_mode_t* idc_char_attr_md, ble_gatts_char_handles_t* p_handles) { ble_gatts_char_md_t char_md; ble_gatts_attr_md_t cccd_md; ble_gatts_attr_md_t attr_md; ble_gatts_attr_t attr_char_value; ble_uuid_t ble_uuid; APP_ERROR_CHECK_BOOL(p_char_value != NULL); APP_ERROR_CHECK_BOOL(char_len > 0); memset(&cccd_md, 0, sizeof(cccd_md)); BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cccd_md.read_perm); BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cccd_md.write_perm); cccd_md.vloc = BLE_GATTS_VLOC_STACK; cccd_md.write_perm = idc_char_attr_md->cccd_write_perm; memset(&char_md, 0, sizeof(char_md)); char_md.char_props.indicate = 1; char_md.p_char_user_desc = NULL; char_md.p_char_pf = NULL; char_md.p_user_desc_md = NULL; char_md.p_cccd_md = &cccd_md; char_md.p_sccd_md = NULL; BLE_UUID_BLE_ASSIGN(ble_uuid, uuid); memset(&attr_md, 0, sizeof(attr_md)); attr_md.vloc = BLE_GATTS_VLOC_STACK; attr_md.read_perm = idc_char_attr_md->read_perm; attr_md.write_perm = idc_char_attr_md->write_perm; attr_md.rd_auth = 0; attr_md.wr_auth = 0; attr_md.vlen = 1; memset(&attr_char_value, 0, sizeof(attr_char_value)); attr_char_value.p_uuid = &ble_uuid; attr_char_value.p_attr_md = &attr_md; attr_char_value.init_len = char_len; attr_char_value.init_offs = 0; attr_char_value.max_len = char_len; attr_char_value.p_value = p_char_value; return sd_ble_gatts_characteristic_add(service_handle, \ &char_md, \ &attr_char_value, \ p_handles); }
/**@brief Display iOS notification message contents * */ static void display_ios_message(void) { bool success; success = nrf6350_lcd_write_string(display_title, strlen(display_title), LCD_UPPER_LINE, 0); APP_ERROR_CHECK_BOOL(success); success = nrf6350_lcd_write_string(display_message, strlen(display_message), LCD_LOWER_LINE, 0); APP_ERROR_CHECK_BOOL(success); display_offset = 0; }
/**@brief Function for receiving and sending data from IRQ. (The same for both IRQs). */ static __INLINE void spi_master_send_recv_irq(spi_master_instance_t * const p_spi_instance) { uint8_t rx_byte; APP_ERROR_CHECK_BOOL(p_spi_instance != NULL); APP_ERROR_CHECK_BOOL(p_spi_instance->state == SPI_MASTER_STATE_BUSY); p_spi_instance->bytes_count++; rx_byte = p_spi_instance->p_nrf_spi->RXD; if (p_spi_instance->start_flag) { p_spi_instance->start_flag = false; spi_master_signal_evt(p_spi_instance, SPI_MASTER_EVT_FIRST_BYTE_RECEIVED, (uint16_t)rx_byte); } else if (p_spi_instance->abort_flag ) //this is tricky, but callback for SPI_MASTER_EVT_FIRST_BYTE_RECEIVED will set this flag for a first byte, which is bad because there is still byte in a buffer { //and for a single byte transaction you will get XFERDONE event to restart p_spi_instance->abort_flag = false; p_spi_instance->state = SPI_MASTER_STATE_ABORTED; nrf_gpio_pin_set(p_spi_instance->pin_slave_select); spi_master_signal_evt(p_spi_instance, SPI_MASTER_EVT_TRANSFER_ABORTED, 0); return; } if ((p_spi_instance->p_rx_buffer != NULL) && (p_spi_instance->rx_index < p_spi_instance->rx_length)) { p_spi_instance->p_rx_buffer[p_spi_instance->rx_index++] = rx_byte; } if ((p_spi_instance->tx_index < p_spi_instance->max_length) && (!(p_spi_instance->abort_flag))) //do not TX if you know that there is an abort to be done - this should work for a DOUBLE BUFFERING ??? { p_spi_instance->p_nrf_spi->TXD = ((p_spi_instance->p_tx_buffer != NULL) && (p_spi_instance->tx_index < p_spi_instance->tx_length)) ? p_spi_instance->p_tx_buffer[p_spi_instance->tx_index] : SPI_DEFAULT_TX_BYTE; (p_spi_instance->tx_index)++; } if (p_spi_instance->bytes_count >= p_spi_instance->max_length) { APP_ERROR_CHECK_BOOL(p_spi_instance->bytes_count == p_spi_instance->max_length); nrf_gpio_pin_set(p_spi_instance->pin_slave_select); p_spi_instance->state = SPI_MASTER_STATE_IDLE; spi_master_signal_evt(p_spi_instance, SPI_MASTER_EVT_TRANSFER_COMPLETED, p_spi_instance->tx_index); } return; }
/**@brief Function for application main entry. */ int main(void) { uint32_t err_code; bool bootloader_is_pushed = false; leds_init(); // This check ensures that the defined fields in the bootloader corresponds with actual // setting in the nRF51 chip. APP_ERROR_CHECK_BOOL(NRF_UICR->CLENR0 == CODE_REGION_1_START); APP_ERROR_CHECK_BOOL(*((uint32_t *)NRF_UICR_BOOT_START_ADDRESS) == BOOTLOADER_REGION_START); APP_ERROR_CHECK_BOOL(NRF_FICR->CODEPAGESIZE == CODE_PAGE_SIZE); // Initialize. timers_init(); gpiote_init(); buttons_init(); ble_stack_init(); scheduler_init(); bootloader_is_pushed = ((nrf_gpio_pin_read(BOOTLOADER_BUTTON_PIN) == 0)? true: false); if (bootloader_is_pushed || (!bootloader_app_is_valid(DFU_BANK_0_REGION_START))) { nrf_gpio_pin_set(LED_2); // Initiate an update of the firmware. err_code = bootloader_dfu_start(); APP_ERROR_CHECK(err_code); nrf_gpio_pin_clear(LED_2); } if (bootloader_app_is_valid(DFU_BANK_0_REGION_START)) { leds_off(); // Select a bank region to use as application region. // @note: Only applications running from DFU_BANK_0_REGION_START is supported. bootloader_app_start(DFU_BANK_0_REGION_START); } nrf_gpio_pin_clear(LED_0); nrf_gpio_pin_clear(LED_1); nrf_gpio_pin_clear(LED_2); nrf_gpio_pin_clear(LED_7); NVIC_SystemReset(); }
/** * @brief Function for initializing TX or RX buffer. */ static __INLINE void spi_master_buffer_init(uint8_t * const p_buf, const uint16_t buf_len, uint8_t * volatile * pp_buf, volatile uint16_t * const p_buf_len, volatile uint16_t * const p_index) { APP_ERROR_CHECK_BOOL(pp_buf != NULL); APP_ERROR_CHECK_BOOL(p_buf_len != NULL); APP_ERROR_CHECK_BOOL(p_index != NULL); *pp_buf = p_buf; *p_buf_len = (p_buf != NULL) ? buf_len : 0; *p_index = 0; }
/**@brief Function for encoding a PnP ID. * * @param[out] p_encoded_buffer Buffer where the encoded data will be written. * @param[in] p_pnp_id PnP ID to be encoded. */ static void pnp_id_encode(uint8_t * p_encoded_buffer, const ble_dis_pnp_id_t * p_pnp_id) { uint8_t len = 0; APP_ERROR_CHECK_BOOL(p_pnp_id != NULL); APP_ERROR_CHECK_BOOL(p_encoded_buffer != NULL); p_encoded_buffer[len++] = p_pnp_id->vendor_id_source; len += uint16_encode(p_pnp_id->vendor_id, &p_encoded_buffer[len]); len += uint16_encode(p_pnp_id->product_id, &p_encoded_buffer[len]); len += uint16_encode(p_pnp_id->product_version, &p_encoded_buffer[len]); APP_ERROR_CHECK_BOOL(len == BLE_DIS_PNP_ID_LEN); }
/**@brief Function for encoding a System ID. * * @param[out] p_encoded_buffer Buffer where the encoded data will be written. * @param[in] p_sys_id System ID to be encoded. */ static void sys_id_encode(uint8_t * p_encoded_buffer, const ble_dis_sys_id_t * p_sys_id) { APP_ERROR_CHECK_BOOL(p_sys_id != NULL); APP_ERROR_CHECK_BOOL(p_encoded_buffer != NULL); p_encoded_buffer[0] = (p_sys_id->manufacturer_id & 0x00000000FF); p_encoded_buffer[1] = (p_sys_id->manufacturer_id & 0x000000FF00) >> 8; p_encoded_buffer[2] = (p_sys_id->manufacturer_id & 0x0000FF0000) >> 16; p_encoded_buffer[3] = (p_sys_id->manufacturer_id & 0x00FF000000) >> 24; p_encoded_buffer[4] = (p_sys_id->manufacturer_id & 0xFF00000000) >> 32; p_encoded_buffer[5] = (p_sys_id->organizationally_unique_id & 0x0000FF); p_encoded_buffer[6] = (p_sys_id->organizationally_unique_id & 0x00FF00) >> 8; p_encoded_buffer[7] = (p_sys_id->organizationally_unique_id & 0xFF0000) >> 16; }
/**@brief Function for SPI master event callback. * * Upon receiving an SPI transaction complete event, checks if received data are valid. * * @param[in] spi_master_evt SPI master driver event. */ static void spi_master_event_handler(spi_master_evt_t spi_master_evt) { uint32_t err_code = NRF_SUCCESS; bool result = false; switch (spi_master_evt.evt_type) { case SPI_MASTER_EVT_TRANSFER_COMPLETED: // Check if data are vaild. result = buf_check(m_rx_data, spi_master_evt.data_count); APP_ERROR_CHECK_BOOL(result); err_code = bsp_indication_set(BSP_INDICATE_RCV_OK); APP_ERROR_CHECK(err_code); // Inform application that transfer is completed. m_transfer_completed = true; break; default: // No implementation needed. break; } }
/**@brief Timeout handler that is responsible for toggling the Advertisement LED. * * @details This function will be called each time the timer that was started for the sake of * blinking the Advertisement LED expires. This function toggle the state of the * Advertisement LED. * * @param[in] p_context Pointer used for passing some arbitrary information (context) from the * app_start_timer() call to the timeout handler. */ static void adv_led_blink_timeout_handler(void * p_context) { if (m_is_adv_led_blinking) { bool * p_is_led_on; uint32_t next_timer_interval; uint32_t err_code; APP_ERROR_CHECK_BOOL(p_context != NULL); nrf_gpio_pin_toggle(ADVERTISING_LED_PIN_NO); p_is_led_on = (bool *)(p_context); *p_is_led_on = !(*p_is_led_on); if(*p_is_led_on ) { // The toggle operation above would have resulted in an ON state. So start a timer that // will expire after ADV_LED_ON_TIME. next_timer_interval = ADV_LED_ON_TIME; } else { // The toggle operation above would have resulted in an OFF state. So start a timer that // will expire after ADV_LED_OFF_TIME. next_timer_interval = ADV_LED_OFF_TIME; } err_code = app_timer_start(m_adv_led_blink_timer_id, next_timer_interval, p_is_led_on ); APP_ERROR_CHECK(err_code); } }
void check_report(int32_t expected) { // only first run is specific... if ((expected > 0) && m_first_report_flag) { expected = expected-1; } else if ((expected < 0) && m_first_report_flag) { expected = expected+1; } APP_ERROR_CHECK_BOOL( m_accdblread == 0); APP_ERROR_CHECK_BOOL( m_accread == expected ); m_first_report_flag = false; // clear silently after first run }
/**@brief Handler for SPI1 master events. * * @param[in] spi_master_evt SPI master event. */ void spi_master_1_event_handler(spi_master_evt_t spi_master_evt) { uint32_t err_code = NRF_SUCCESS; bool result = false; switch (spi_master_evt.evt_type) { case SPI_MASTER_EVT_TRANSFER_COMPLETED: // Check if received data is correct. result = check_buf_equal(m_tx_data_spi, m_rx_data_spi, TX_RX_MSG_LENGTH); APP_ERROR_CHECK_BOOL(result); // Close SPI master. spi_master_close(SPI_MASTER_1); err_code = bsp_indication_set(BSP_INDICATE_RCV_OK); APP_ERROR_CHECK(err_code); m_transfer_completed = true; break; default: // No implementation needed. break; } }
void spi_master_close(const spi_master_hw_instance_t spi_master_hw_instance) { #if defined(SPI_MASTER_0_ENABLE) || defined(SPI_MASTER_1_ENABLE) volatile spi_master_instance_t * p_spi_instance = spi_master_get_instance( spi_master_hw_instance); APP_ERROR_CHECK_BOOL(p_spi_instance != NULL); /* Disable interrupt */ APP_ERROR_CHECK(sd_nvic_ClearPendingIRQ(p_spi_instance->irq_type)); APP_ERROR_CHECK(sd_nvic_DisableIRQ(p_spi_instance->irq_type)); p_spi_instance->p_nrf_spi->ENABLE = (SPI_ENABLE_ENABLE_Disabled << SPI_ENABLE_ENABLE_Pos); /* Set Slave Select pin as input with pull-up. */ nrf_gpio_pin_set(p_spi_instance->pin_slave_select); nrf_gpio_cfg_input(p_spi_instance->pin_slave_select, NRF_GPIO_PIN_PULLUP); p_spi_instance->pin_slave_select = (uint8_t)0xFF; /* Disconnect pins from SPI hardware */ p_spi_instance->p_nrf_spi->PSELSCK = (uint32_t)SPI_PIN_DISCONNECTED; p_spi_instance->p_nrf_spi->PSELMOSI = (uint32_t)SPI_PIN_DISCONNECTED; p_spi_instance->p_nrf_spi->PSELMISO = (uint32_t)SPI_PIN_DISCONNECTED; /* Reset to default values */ spi_master_init_hw_instance(NULL, (IRQn_Type)0, p_spi_instance, false); #else return; #endif }
/** * @brief Function for initializing instance of SPI master by default values. */ static __INLINE void spi_master_init_hw_instance(NRF_SPI_Type * p_nrf_spi, IRQn_Type irq_type, volatile spi_master_instance_t * p_spi_instance, volatile bool disable_all_irq) { APP_ERROR_CHECK_BOOL(p_spi_instance != NULL); p_spi_instance->p_nrf_spi = p_nrf_spi; p_spi_instance->irq_type = irq_type; p_spi_instance->p_tx_buffer = NULL; p_spi_instance->tx_length = 0; p_spi_instance->tx_index = 0; p_spi_instance->p_rx_buffer = NULL; p_spi_instance->rx_length = 0; p_spi_instance->rx_index = 0; p_spi_instance->bytes_count = 0; p_spi_instance->max_length = 0; p_spi_instance->pin_slave_select = 0; p_spi_instance->callback_event_handler = NULL; p_spi_instance->state = SPI_MASTER_STATE_DISABLED; p_spi_instance->started_flag = false; p_spi_instance->disable_all_irq = disable_all_irq; }
/**@brief Function for receiving callbacks from the micro-esb library. */ static void uesb_event_handler(void) { uint32_t rf_interrupts; uesb_get_clear_interrupts(&rf_interrupts); if(rf_interrupts & UESB_INT_TX_FAILED_MSK) { // Transmit failed: flush buffer uesb_flush_tx(); m_tx_attempts += 1; m_ut_state = UT_STATE_RX; } if (rf_interrupts & UESB_INT_TX_SUCCESS_MSK) { uesb_payload_t payload; uint32_t payload_len; // Successful transmission. Can now remove packet from our FIFO payload_len = sizeof(payload); fifo_get_pkt(&m_transmit_fifo, (uint8_t *) &payload, &payload_len); APP_ERROR_CHECK_BOOL(payload_len == sizeof(payload)); m_tx_attempts = 0; m_ut_state = UT_STATE_RX; } if(rf_interrupts & UESB_INT_RX_DR_MSK) { // Data reception is handled in a lower priority interrupt NVIC_SetPendingIRQ(UESB_RX_HANDLE_IRQn); } }
static void app_timer_evt_get(void * p_event_data, uint16_t event_size) { app_timer_event_t * p_timer_event = (app_timer_event_t *)p_event_data; APP_ERROR_CHECK_BOOL(event_size == sizeof(app_timer_event_t)); p_timer_event->timeout_handler(p_timer_event->p_context); }
/**@brief HID Report Characteristic Write event handler. * * @param[in] p_evt HID service event. */ static void on_hid_rep_char_write(ble_hids_evt_t *p_evt) { if (p_evt->params.char_write.char_id.rep_type == BLE_HIDS_REP_TYPE_OUTPUT) { uint32_t err_code; uint8_t report_val; uint8_t report_index = p_evt->params.char_write.char_id.rep_index; if (report_index == OUTPUT_REPORT_INDEX) { APP_ERROR_CHECK_BOOL(OUTPUT_REPORT_MAX_LEN == 1); err_code = ble_hids_outp_rep_get(&m_hids, report_index, OUTPUT_REPORT_MAX_LEN, 0, &report_val); APP_ERROR_CHECK(err_code); if ((report_val & OUTPUT_REPORT_BIT_MASK_CAPS_LOCK) != 0) { // Caps Lock On nrf_gpio_pin_set(CAPS_ON_LED_PIN_NO); keys_send(sizeof(m_caps_on_key_pattern), m_caps_on_key_pattern); } else { // Caps Lock Off nrf_gpio_pin_clear(CAPS_ON_LED_PIN_NO); keys_send(sizeof(m_caps_off_key_pattern), m_caps_off_key_pattern); } } } }
/**@brief Function for application main entry. */ int main(void) { uint32_t err_code; bool bootloader_is_pushed = false; static uint32_t TestAdr; TestAdr = (uint32_t)*(&(BluetoothDFU)); if(TestAdr == 100) { bootloader_is_pushed = true; F_flash_page_erase(&BluetoothDFU); ble_flash_word_write(&BluetoothDFU , 0); } // This check ensures that the defined fields in the bootloader corresponds with actual // setting in the nRF51 chip. APP_ERROR_CHECK_BOOL(NRF_UICR->CLENR0 == CODE_REGION_1_START); APP_ERROR_CHECK_BOOL(*((uint32_t *)NRF_UICR_BOOT_START_ADDRESS) == BOOTLOADER_REGION_START); APP_ERROR_CHECK_BOOL(NRF_FICR->CODEPAGESIZE == CODE_PAGE_SIZE); // Initialize. timers_init(); gpiote_init(); buttons_init(); ble_stack_init(); scheduler_init(); //bootloader_is_pushed = ((nrf_gpio_pin_read(BOOTLOADER_BUTTON_PIN) == 0)? true: false); if (bootloader_is_pushed || (!bootloader_app_is_valid(DFU_BANK_0_REGION_START))) { // Initiate an update of the firmware. err_code = bootloader_dfu_start(); APP_ERROR_CHECK(err_code); } if (bootloader_app_is_valid(DFU_BANK_0_REGION_START)) { // Select a bank region to use as application region. // @note: Only applications running from DFU_BANK_0_REGION_START is supported. bootloader_app_start(DFU_BANK_0_REGION_START); } NVIC_SystemReset(); }
/**@brief IRQHandler used for execution context management. * Any available handler can be used as we're not using the associated hardware. * This handler is used to initiate UESB RX/TX */ void TIMESLOT_BEGIN_IRQHandler(void) { uesb_payload_t payload; uint32_t payload_len; uint32_t err_code; uesb_init(&m_uesb_config); // Packet transmission is syncrhonized to the beginning of timeslots // Check FIFO for packets and transmit if not empty if (m_transmit_fifo.free_items < sizeof(m_transmit_fifo.buf) && m_ut_state != UT_STATE_TX) { // There are packets in the FIFO: Start transmitting payload_len = sizeof(payload); // Copy packet from FIFO. Packet isn't removed until transmissions succeeds or max retries has been exceeded if (m_tx_attempts < MAX_TX_ATTEMPTS) { fifo_peek_pkt(&m_transmit_fifo, (uint8_t *) &payload, &payload_len); APP_ERROR_CHECK_BOOL(payload_len == sizeof(payload)); } else { fifo_get_pkt(&m_transmit_fifo, (uint8_t *) &payload, &payload_len); APP_ERROR_CHECK_BOOL(payload_len == sizeof(payload)); m_tx_attempts = 0; } if (m_ut_state == UT_STATE_RX) { uesb_stop_rx(); } err_code = uesb_write_tx_payload(&payload); APP_ERROR_CHECK(err_code); m_ut_state = UT_STATE_TX; } else { // No packets in the FIFO: start reception err_code = uesb_start_rx(); m_ut_state = UT_STATE_RX; } }
uint32_t ble_hids_boot_mouse_inp_rep_send(ble_hids_t * p_hids, uint8_t buttons, int8_t x_delta, int8_t y_delta, uint16_t optional_data_len, uint8_t * p_optional_data) { uint32_t err_code; if (p_hids->conn_handle != BLE_CONN_HANDLE_INVALID) { uint16_t hvx_len = BOOT_MOUSE_INPUT_REPORT_MIN_SIZE + optional_data_len; if (hvx_len <= BOOT_MOUSE_INPUT_REPORT_MAX_SIZE) { uint8_t buffer[BOOT_MOUSE_INPUT_REPORT_MAX_SIZE]; ble_gatts_hvx_params_t hvx_params; APP_ERROR_CHECK_BOOL(BOOT_MOUSE_INPUT_REPORT_MIN_SIZE == 3); // Build buffer buffer[0] = buttons; buffer[1] = (uint8_t)x_delta; buffer[2] = (uint8_t)y_delta; if (optional_data_len > 0) { memcpy(&buffer[3], p_optional_data, optional_data_len); } // Pass buffer to stack memset(&hvx_params, 0, sizeof(hvx_params)); hvx_params.handle = p_hids->boot_mouse_inp_rep_handles.value_handle; hvx_params.type = BLE_GATT_HVX_NOTIFICATION; hvx_params.offset = 0; hvx_params.p_len = &hvx_len; hvx_params.p_data = buffer; err_code = sd_ble_gatts_hvx(p_hids->conn_handle, &hvx_params); if ((err_code == NRF_SUCCESS) && (hvx_len != BOOT_MOUSE_INPUT_REPORT_MIN_SIZE + optional_data_len) ) { err_code = NRF_ERROR_DATA_SIZE; } } else { err_code = NRF_ERROR_DATA_SIZE; } } else { err_code = NRF_ERROR_INVALID_STATE; } return err_code; }
void bootloader_enable(void) { #ifdef RBC_MESH_SERIAL mesh_aci_start(); #endif bl_cmd_t enable_cmd; enable_cmd.type = BL_CMD_TYPE_ENABLE; bl_cmd_handler(&enable_cmd); transport_start(); /* Recover from broken state */ if (dfu_mesh_app_is_valid()) { set_timeout(TIMER_YIELD_TIMEOUT, TIMEOUT_ACTION_GO_TO_APP); } else { #ifdef RTT_LOG __LOG(RTT_CTRL_TEXT_RED "APP is invalid.\n"); bl_info_flags_t* p_flags = &bootloader_info_entry_get(BL_INFO_TYPE_FLAGS)->flags; bl_info_segment_t* p_seg = &bootloader_info_entry_get(BL_INFO_TYPE_SEGMENT_APP)->segment; __LOG("\tINTACT: SD: %d APP: %d BL: %d\n", p_flags->sd_intact, p_flags->app_intact, p_flags->bl_intact); if (*((uint32_t*) p_seg->start) == 0xFFFFFFFF) { __LOG("\tNo application at 0x%x\n", p_seg->start); } #endif /* update the bootloader if a bank is available */ if (dfu_bank_flash(DFU_TYPE_BOOTLOADER) == NRF_SUCCESS) { return; } dfu_type_t missing = dfu_mesh_missing_type_get(); if (missing != DFU_TYPE_NONE && dfu_bank_flash(missing) == NRF_ERROR_NOT_FOUND) { fwid_union_t req_fwid; bl_info_entry_t* p_fwid_entry = bootloader_info_entry_get(BL_INFO_TYPE_VERSION); APP_ERROR_CHECK_BOOL(p_fwid_entry != NULL); switch (missing) { case DFU_TYPE_SD: req_fwid.sd = p_fwid_entry->version.sd; break; case DFU_TYPE_APP: req_fwid.app = p_fwid_entry->version.app; break; default: APP_ERROR_CHECK(NRF_ERROR_INVALID_DATA); } dfu_mesh_req(missing, &req_fwid, (uint32_t*) 0xFFFFFFFF); } } }
/**@brief Display an iOS notification * */ void evt_ios_notification(ble_ancs_c_evt_ios_notification_t *p_notice) { bool success; char buffer[DISPLAY_BUFFER_SIZE]; success = nrf6350_lcd_write_string(lit_catid[p_notice->category_id], strlen(lit_catid[p_notice->category_id]), LCD_UPPER_LINE, 0); APP_ERROR_CHECK_BOOL(success); sprintf(buffer, "%s %02x%02x%02x%02x", lit_eventid[p_notice->event_id], p_notice->notification_uid[0], p_notice->notification_uid[1], p_notice->notification_uid[2], p_notice->notification_uid[3]); success = nrf6350_lcd_write_string(buffer, strlen(buffer), LCD_LOWER_LINE, 0); APP_ERROR_CHECK_BOOL(success); }
/** @brief Function for executing method for entering calibration not active state. * * Execute method for entering calibration not active state, meaning notifying the application of * the state entry event. Additionally, if the timeout handler is running, it will be stopped. */ static __INLINE void calibration_not_active_execute(void) { const uint32_t err_code = app_timer_stop(m_timer_id); APP_ERROR_CHECK(err_code); APP_ERROR_CHECK_BOOL(m_calibration_process_callback != NULL); m_calibration_process_callback(CALIBRATION_NOT_ACTIVE_STATE_ENTER); }
/**@brief Function for adding the Characteristic. * * @param[in] uuid UUID of characteristic to be added. * @param[in] p_char_value Initial value of characteristic to be added. * @param[in] char_len Length of initial value. This will also be the maximum value. * @param[in] dis_attr_md Security settings of characteristic to be added. * @param[out] p_handles Handles of new characteristic. * * @return NRF_SUCCESS on success, otherwise an error code. */ static uint32_t char_add(uint16_t uuid, uint8_t * p_char_value, uint16_t char_len, const ble_srv_security_mode_t * dis_attr_md, ble_gatts_char_handles_t * p_handles) { ble_uuid_t ble_uuid; ble_gatts_char_md_t char_md; ble_gatts_attr_t attr_char_value; ble_gatts_attr_md_t attr_md; APP_ERROR_CHECK_BOOL(p_char_value != NULL); APP_ERROR_CHECK_BOOL(char_len > 0); // The ble_gatts_char_md_t structure uses bit fields. So we reset the memory to zero. memset(&char_md, 0, sizeof(char_md)); char_md.char_props.read = 1; char_md.p_char_user_desc = NULL; char_md.p_char_pf = NULL; char_md.p_user_desc_md = NULL; char_md.p_cccd_md = NULL; char_md.p_sccd_md = NULL; BLE_UUID_BLE_ASSIGN(ble_uuid, uuid); memset(&attr_md, 0, sizeof(attr_md)); attr_md.read_perm = dis_attr_md->read_perm; attr_md.write_perm = dis_attr_md->write_perm; attr_md.vloc = BLE_GATTS_VLOC_STACK; attr_md.rd_auth = 0; attr_md.wr_auth = 0; attr_md.vlen = 0; memset(&attr_char_value, 0, sizeof(attr_char_value)); attr_char_value.p_uuid = &ble_uuid; attr_char_value.p_attr_md = &attr_md; attr_char_value.init_len = char_len; attr_char_value.init_offs = 0; attr_char_value.max_len = char_len; attr_char_value.p_value = p_char_value; return sd_ble_gatts_characteristic_add(service_handle, &char_md, &attr_char_value, p_handles); }
/**@brief Function for processing a received vendor specific packet. * * @param[in] p_buffer Pointer to the packet data. * @param[in] length Length of packet data in bytes. */ static void rx_vendor_specific_pkt_type_handle(const uint8_t * p_buffer, uint32_t length) { // @note: no pointer validation check needed as allready checked by calling function. uint32_t err_code; if (is_rx_pkt_valid(p_buffer, length)) { // RX packet is valid: validate sequence number. const uint8_t rx_seq_number = packet_seq_nmbr_extract(p_buffer); if (packet_number_expected_get() == rx_seq_number) { // Sequence number is valid: transmit acknowledgement. packet_number_expected_inc(); ack_transmit(); m_is_slip_decode_ready = true; err_code = hci_mem_pool_rx_data_size_set(length); APP_ERROR_CHECK(err_code); err_code = hci_mem_pool_rx_produce(HCI_RX_BUF_SIZE, (void **)&mp_slip_used_rx_buffer); APP_ERROR_CHECK_BOOL((err_code == NRF_SUCCESS) || (err_code == NRF_ERROR_NO_MEM)); // If memory pool RX buffer produce succeeded we register that buffer to slip layer // otherwise we register the internal acknowledgement buffer. err_code = hci_slip_rx_buffer_register( (err_code == NRF_SUCCESS) ? mp_slip_used_rx_buffer : m_rx_ack_buffer, (err_code == NRF_SUCCESS) ? HCI_RX_BUF_SIZE : ACK_BUF_SIZE); APP_ERROR_CHECK(err_code); if (m_transport_event_handle != NULL) { // Send application event of RX packet reception. const hci_transport_evt_t evt = {HCI_TRANSPORT_RX_RDY}; m_transport_event_handle(evt); } } else { // RX packet discarded: sequence number not valid, set the same buffer to slip layer in // order to avoid buffer overrun. err_code = hci_slip_rx_buffer_register(mp_slip_used_rx_buffer, HCI_RX_BUF_SIZE); APP_ERROR_CHECK(err_code); // As packet did not have expected sequence number: send acknowledgement with the // current expected sequence number. ack_transmit(); } } else { // RX packet discarded: reset the same buffer to slip layer in order to avoid buffer // overrun. err_code = hci_slip_rx_buffer_register(mp_slip_used_rx_buffer, HCI_RX_BUF_SIZE); APP_ERROR_CHECK(err_code); } }
/**@brief Connection Parameters Module handler. * * @details This function will be called for all events in the Connection Parameters Module which * are passed to the application. * @note All this function does is to disconnect. This could have been done by simply * setting the disconnect_on_fail config parameter, but instead we use the event * handler mechanism to demonstrate its use. * * @param[in] p_evt Event received from the Connection Parameters Module. */ static void on_conn_params_evt(ble_conn_params_evt_t * p_evt) { uint32_t err_code; APP_ERROR_CHECK_BOOL(p_evt->evt_type == BLE_CONN_PARAMS_EVT_FAILED); err_code = sd_ble_gap_disconnect(m_conn_handle, BLE_HCI_CONN_INTERVAL_UNACCEPTABLE); APP_ERROR_CHECK(err_code); }