static void a2dp_demo_timer_stop(a2dp_media_sending_context_t * context){ context->time_audio_data_sent = 0; context->acc_num_missed_samples = 0; context->samples_ready = 0; context->streaming = 1; context->sbc_storage_count = 0; context->sbc_ready_to_send = 0; btstack_run_loop_remove_timer(&context->audio_timer); }
static void a2dp_demo_timer_start(a2dp_media_sending_context_t * context){ context->max_media_payload_size = 0x290;// avdtp_max_media_payload_size(context->local_seid); context->sbc_storage_count = 0; context->sbc_ready_to_send = 0; context->streaming = 1; btstack_run_loop_remove_timer(&context->audio_timer); btstack_run_loop_set_timer_handler(&context->audio_timer, avdtp_audio_timeout_handler); btstack_run_loop_set_timer_context(&context->audio_timer, context); btstack_run_loop_set_timer(&context->audio_timer, AUDIO_TIMEOUT_MS); btstack_run_loop_add_timer(&context->audio_timer); }
/** * Execute run_loop once */ void btstack_run_loop_embedded_execute_once(void) { btstack_data_source_t *ds; // process data sources btstack_data_source_t *next; for (ds = (btstack_data_source_t *) data_sources; ds != NULL ; ds = next){ next = (btstack_data_source_t *) ds->item.next; // cache pointer to next data_source to allow data source to remove itself if (ds->flags & DATA_SOURCE_CALLBACK_POLL){ ds->process(ds, DATA_SOURCE_CALLBACK_POLL); } } #ifdef TIMER_SUPPORT #ifdef HAVE_EMBEDDED_TICK uint32_t now = system_ticks; #endif #ifdef HAVE_EMBEDDED_TIME_MS uint32_t now = hal_time_ms(); #endif // process timers while (timers) { btstack_timer_source_t *ts = (btstack_timer_source_t *) timers; uint32_t timeout_low = ts->timeout; int timeout_high = btstack_run_loop_embedded_reconstruct_higher_bits(now, timeout_low); if (timeout_high > 0 || ((timeout_high == 0) && (timeout_low > now))) break; btstack_run_loop_remove_timer(ts); ts->process(ts); } #endif // disable IRQs and check if run loop iteration has been requested. if not, go to sleep hal_cpu_disable_irqs(); if (trigger_event_received){ trigger_event_received = 0; hal_cpu_enable_irqs(); } else { hal_cpu_enable_irqs_and_sleep(); } }
static void a2dp_demo_timer_pause(a2dp_media_sending_context_t * context){ btstack_run_loop_remove_timer(&context->audio_timer); }
static void att_packet_handler(uint8_t packet_type, uint16_t handle, uint8_t *packet, uint16_t size){ att_server_t * att_server; switch (packet_type){ case HCI_EVENT_PACKET: switch (packet[0]){ case L2CAP_EVENT_CAN_SEND_NOW: att_server_handle_can_send_now(); break; case ATT_EVENT_MTU_EXCHANGE_COMPLETE: // GATT client has negotiated the mtu for this connection att_server = att_server_for_handle(handle); if (!att_server) break; att_server->connection.mtu = little_endian_read_16(packet, 4); break; default: break; } break; case ATT_DATA_PACKET: log_debug("ATT Packet, handle 0x%04x", handle); att_server = att_server_for_handle(handle); if (!att_server) break; // handle value indication confirms if (packet[0] == ATT_HANDLE_VALUE_CONFIRMATION && att_server->value_indication_handle){ btstack_run_loop_remove_timer(&att_server->value_indication_timer); uint16_t att_handle = att_server->value_indication_handle; att_server->value_indication_handle = 0; att_handle_value_indication_notify_client(0, att_server->connection.con_handle, att_handle); return; } // directly process command // note: signed write cannot be handled directly as authentication needs to be verified if (packet[0] == ATT_WRITE_COMMAND){ att_handle_request(&att_server->connection, packet, size, 0); return; } // check size if (size > sizeof(att_server->request_buffer)) { log_info("att_packet_handler: dropping att pdu 0x%02x as size %u > att_server->request_buffer %u", packet[0], size, (int) sizeof(att_server->request_buffer)); return; } // last request still in processing? if (att_server->state != ATT_SERVER_IDLE){ log_info("att_packet_handler: skipping att pdu 0x%02x as server not idle (state %u)", packet[0], att_server->state); return; } // store request att_server->state = ATT_SERVER_REQUEST_RECEIVED; att_server->request_size = size; memcpy(att_server->request_buffer, packet, size); att_run_for_context(att_server); break; } }
/** * Execute run_loop */ static void btstack_run_loop_posix_execute(void) { fd_set descriptors_read; fd_set descriptors_write; btstack_timer_source_t *ts; btstack_linked_list_iterator_t it; struct timeval * timeout; struct timeval tv; uint32_t now_ms; while (1) { // collect FDs FD_ZERO(&descriptors_read); FD_ZERO(&descriptors_write); int highest_fd = -1; btstack_linked_list_iterator_init(&it, &data_sources); while (btstack_linked_list_iterator_has_next(&it)){ btstack_data_source_t *ds = (btstack_data_source_t*) btstack_linked_list_iterator_next(&it); if (ds->fd < 0) continue; if (ds->flags & DATA_SOURCE_CALLBACK_READ){ FD_SET(ds->fd, &descriptors_read); if (ds->fd > highest_fd) { highest_fd = ds->fd; } log_debug("btstack_run_loop_execute adding fd %u for read", ds->fd); } if (ds->flags & DATA_SOURCE_CALLBACK_WRITE){ FD_SET(ds->fd, &descriptors_write); if (ds->fd > highest_fd) { highest_fd = ds->fd; } log_debug("btstack_run_loop_execute adding fd %u for write", ds->fd); } } // get next timeout timeout = NULL; if (timers) { ts = (btstack_timer_source_t *) timers; timeout = &tv; now_ms = btstack_run_loop_posix_get_time_ms(); int delta = ts->timeout - now_ms; if (delta < 0){ delta = 0; } tv.tv_sec = delta / 1000; tv.tv_usec = (delta - (tv.tv_sec * 1000)) * 1000; log_debug("btstack_run_loop_execute next timeout in %u ms", delta); } // wait for ready FDs select( highest_fd+1 , &descriptors_read, &descriptors_write, NULL, timeout); data_sources_modified = 0; btstack_linked_list_iterator_init(&it, &data_sources); while (btstack_linked_list_iterator_has_next(&it) && !data_sources_modified){ btstack_data_source_t *ds = (btstack_data_source_t*) btstack_linked_list_iterator_next(&it); log_debug("btstack_run_loop_posix_execute: check ds %p with fd %u\n", ds, ds->fd); if (FD_ISSET(ds->fd, &descriptors_read)) { log_debug("btstack_run_loop_posix_execute: process read ds %p with fd %u\n", ds, ds->fd); ds->process(ds, DATA_SOURCE_CALLBACK_READ); } if (FD_ISSET(ds->fd, &descriptors_write)) { log_debug("btstack_run_loop_posix_execute: process write ds %p with fd %u\n", ds, ds->fd); ds->process(ds, DATA_SOURCE_CALLBACK_WRITE); } } log_debug("btstack_run_loop_posix_execute: after ds check\n"); // process timers now_ms = btstack_run_loop_posix_get_time_ms(); while (timers) { ts = (btstack_timer_source_t *) timers; if (ts->timeout > now_ms) break; log_debug("btstack_run_loop_posix_execute: process timer %p\n", ts); // remove timer before processing it to allow handler to re-register with run loop btstack_run_loop_remove_timer(ts); ts->process(ts); } } }