static void att_packet_handler(uint8_t packet_type, uint16_t handle, uint8_t *packet, uint16_t size){ if (packet_type != ATT_DATA_PACKET) return; // handle value indication confirms if (packet[0] == ATT_HANDLE_VALUE_CONFIRMATION && att_handle_value_indication_handle){ run_loop_remove_timer(&att_handle_value_indication_timer); uint16_t att_handle = att_handle_value_indication_handle; att_handle_value_indication_handle = 0; att_handle_value_indication_notify_client(0, att_connection.con_handle, att_handle); return; } // check size if (size > sizeof(att_request_buffer)) return; // last request still in processing? if (att_server_state != ATT_SERVER_IDLE) return; // store request att_server_state = ATT_SERVER_REQUEST_RECEIVED; att_request_size = size; memcpy(att_request_buffer, packet, size); att_run(); }
/** * Execute run_loop once */ void embedded_execute_once(void) { // refresh system_ticks system_ticks = btstack_get_time(); data_source_t *ds; // process data sources data_source_t *next; for (ds = (data_source_t *) data_sources; ds != NULL ; ds = next){ next = (data_source_t *) ds->item.next; // cache pointer to next data_source to allow data source to remove itself ds->process(ds); } #ifdef HAVE_TICK // process timers while (timers) { timer_source_t *ts = (timer_source_t *) timers; if (ts->timeout > system_ticks) break; 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(); // } }
/** * Execute run_loop once */ void embedded_execute_once(void) { data_source_t *ds; // process data sources data_source_t *next; for (ds = (data_source_t *) data_sources; ds != NULL ; ds = next){ next = (data_source_t *) ds->item.next; // cache pointer to next data_source to allow data source to remove itself ds->process(ds); } #ifdef HAVE_TICK uint32_t now = system_ticks; #endif #ifdef HAVE_TIME_MS uint32_t now = hal_time_ms(); #endif #ifdef TIMER_SUPPORT // process timers while (timers) { timer_source_t *ts = (timer_source_t *) timers; if (ts->timeout > now) break; 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 stop_power_off_timer(void){ #ifdef USE_POWER_OFF_TIMER if (timeout_active) { run_loop_remove_timer(&timeout); timeout_active = 0; } #endif }
static void h4_enforce_wake_off(void) { run_loop_remove_timer(&hci_transport_h4->sleep_timer); if (enforce_wake_fd) { close(enforce_wake_fd); enforce_wake_fd = 0; } }
static void h4_enforce_wake_on(void) { if (!enforce_wake_device) return; if (!enforce_wake_fd) { enforce_wake_fd = open(enforce_wake_device, O_RDWR); usleep(HCI_WAKE_DURATION); // wait until device is ready } run_loop_remove_timer(&hci_transport_h4->sleep_timer); run_loop_set_timer(&hci_transport_h4->sleep_timer, HCI_WAKE_TIMER_MS); hci_transport_h4->sleep_timer.process = h4_enforce_wake_timeout; run_loop_add_timer(&hci_transport_h4->sleep_timer); }
static void hci_shutdown_connection(hci_connection_t *conn){ log_info("Connection closed: handle %u, %s\n", conn->con_handle, bd_addr_to_str(conn->address)); // cancel all l2cap connections hci_emit_disconnection_complete(conn->con_handle, 0x16); // terminated by local host run_loop_remove_timer(&conn->timeout); linked_list_remove(&hci_stack.connections, (linked_item_t *) conn); btstack_memory_hci_connection_free( conn ); // now it's gone hci_emit_nr_connections_changed(); }
/** * Execute run_loop */ void embedded_execute(void) { data_source_t *ds; while (1) { USBHostTasks(); // process data sources data_source_t *next; for (ds = (data_source_t *) data_sources; ds != NULL ; ds = next){ next = (data_source_t *) ds->item.next; // cache pointer to next data_source to allow data source to remove itself ds->process(ds); } #ifdef HAVE_TICK // process timers while (timers) { timer_source_t *ts = (timer_source_t *) timers; if (ts->timeout > system_ticks) break; run_loop_remove_timer(ts); ts->process(ts); } #endif #if USE_SPP_SERVER || USE_DUALSHOCK3_RUMBLE sendchar(); #endif // disable IRQs and check if run loop iteration has been requested. if not, go to sleep #if 0 hal_cpu_disable_irqs(); if (trigger_event_received){ hal_cpu_enable_irqs_and_sleep(); continue; } hal_cpu_enable_irqs(); #else Idle(); #endif #ifndef __DEBUG if(!deviceAddress){ Reset(); } #endif } }
static void att_packet_handler(uint8_t packet_type, uint16_t handle, uint8_t *packet, uint16_t size){ if (packet_type != ATT_DATA_PACKET) return; // handle value indication confirms if (packet[0] == ATT_HANDLE_VALUE_CONFIRMATION && att_handle_value_indication_handle){ run_loop_remove_timer(&att_handle_value_indication_timer); uint16_t att_handle = att_handle_value_indication_handle; att_handle_value_indication_handle = 0; att_handle_value_indication_notify_client(0, att_connection.con_handle, att_handle); return; } // directly process commands // note: signed write cannot be handled directly as authentication needs to be verified if (packet[0] == ATT_WRITE_COMMAND){ att_handle_request(&att_connection, packet, size, 0); return; } // check size if (size > sizeof(att_request_buffer)) { log_info("att_packet_handler: dropping att pdu 0x%02x as size %u > att_request_buffer %u", packet[0], size, (int) sizeof(att_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_request_size = size; memcpy(att_request_buffer, packet, size); att_run(); }
static int usb_close(void *transport_config){ int c; // @TODO: remove all run loops! switch (libusb_state){ case LIB_USB_CLOSED: break; case LIB_USB_TRANSFERS_ALLOCATED: libusb_state = LIB_USB_INTERFACE_CLAIMED; if(usb_timer_active) { run_loop_remove_timer(&usb_timer); usb_timer_active = 0; } // Cancel any asynchronous transfers for (c = 0 ; c < ASYNC_BUFFERS ; c++) { libusb_cancel_transfer(event_in_transfer[c]); libusb_cancel_transfer(acl_in_transfer[c]); #ifdef HAVE_SCO libusb_cancel_transfer(sco_in_transfer[c]); #endif } /* TODO - find a better way to ensure that all transfers have completed */ struct timeval tv; memset(&tv, 0, sizeof(struct timeval)); libusb_handle_events_timeout(NULL, &tv); if (doing_pollfds){ int r; for (r = 0 ; r < num_pollfds ; r++) { data_source_t *ds = &pollfd_data_sources[r]; run_loop_remove_data_source(ds); } free(pollfd_data_sources); pollfd_data_sources = NULL; num_pollfds = 0; doing_pollfds = 0; } case LIB_USB_INTERFACE_CLAIMED: for (c = 0 ; c < ASYNC_BUFFERS ; c++) { if (event_in_transfer[c]) libusb_free_transfer(event_in_transfer[c]); if (acl_in_transfer[c]) libusb_free_transfer(acl_in_transfer[c]); #ifdef HAVE_SCO if (sco_in_transfer[c]) libusb_free_transfer(sco_in_transfer[c]); #endif } // TODO free control and acl out transfers libusb_release_interface(handle, 0); case LIB_USB_DEVICE_OPENDED: libusb_close(handle); case LIB_USB_OPENED: libusb_exit(NULL); } libusb_state = LIB_USB_CLOSED; handle = NULL; return 0; }
static void hsp_ringing_timer_stop(void){ run_loop_remove_timer(&hs_timeout); }
static void hsp_ringing_timer_start(void){ run_loop_remove_timer(&hs_timeout); run_loop_set_timer_handler(&hs_timeout, hsp_ringing_timeout_handler); run_loop_set_timer(&hs_timeout, 2000); // 2 seconds timeout run_loop_add_timer(&hs_timeout); }
/** * Execute run_loop */ static void posix_execute(void) { fd_set descriptors; timer_source_t *ts; struct timeval current_tv; struct timeval next_tv; struct timeval *timeout; linked_list_iterator_t it; while (1) { // collect FDs FD_ZERO(&descriptors); int highest_fd = 0; linked_list_iterator_init(&it, &data_sources); while (linked_list_iterator_has_next(&it)){ data_source_t *ds = (data_source_t*) linked_list_iterator_next(&it); if (ds->fd >= 0) { FD_SET(ds->fd, &descriptors); if (ds->fd > highest_fd) { highest_fd = ds->fd; } } } // get next timeout // pre: 0 <= tv_usec < 1000000 timeout = NULL; if (timers) { gettimeofday(¤t_tv, NULL); ts = (timer_source_t *) timers; next_tv.tv_usec = ts->timeout.tv_usec - current_tv.tv_usec; next_tv.tv_sec = ts->timeout.tv_sec - current_tv.tv_sec; while (next_tv.tv_usec < 0){ next_tv.tv_usec += 1000000; next_tv.tv_sec--; } if (next_tv.tv_sec < 0){ next_tv.tv_sec = 0; next_tv.tv_usec = 0; } timeout = &next_tv; } // wait for ready FDs select( highest_fd+1 , &descriptors, NULL, NULL, timeout); // process data sources very carefully // bt_control.close() triggered from a client can remove a different data source // log_info("posix_execute: before ds check\n"); data_sources_modified = 0; linked_list_iterator_init(&it, &data_sources); while (linked_list_iterator_has_next(&it) && !data_sources_modified){ data_source_t *ds = (data_source_t*) linked_list_iterator_next(&it); // log_info("posix_execute: check %x with fd %u\n", (int) ds, ds->fd); if (FD_ISSET(ds->fd, &descriptors)) { // log_info("posix_execute: process %x with fd %u\n", (int) ds, ds->fd); ds->process(ds); } } // log_info("posix_execute: after ds check\n"); // process timers // pre: 0 <= tv_usec < 1000000 while (timers) { gettimeofday(¤t_tv, NULL); ts = (timer_source_t *) timers; if (ts->timeout.tv_sec > current_tv.tv_sec) break; if (ts->timeout.tv_sec == current_tv.tv_sec && ts->timeout.tv_usec > current_tv.tv_usec) break; // log_info("posix_execute: process times %x\n", (int) ts); // remove timer before processing it to allow handler to re-register with run loop run_loop_remove_timer(ts); ts->process(ts); } } }