/******************************************************************************* ** ** Function port_set_defaults ** ** Description Set defualt port parameters ** ** *******************************************************************************/ void port_set_defaults (tPORT *p_port) { p_port->ev_mask = 0; p_port->p_callback = NULL; p_port->port_ctrl = 0; p_port->error = 0; p_port->line_status = 0; p_port->rx_flag_ev_pending = FALSE; p_port->peer_mtu = RFCOMM_DEFAULT_MTU; p_port->user_port_pars = default_port_pars; p_port->peer_port_pars = default_port_pars; p_port->credit_tx = 0; p_port->credit_rx = 0; /* p_port->credit_rx_max = PORT_CREDIT_RX_MAX; Determined later */ /* p_port->credit_rx_low = PORT_CREDIT_RX_LOW; Determined later */ memset (&p_port->local_ctrl, 0, sizeof (p_port->local_ctrl)); memset (&p_port->peer_ctrl, 0, sizeof (p_port->peer_ctrl)); memset (&p_port->rx, 0, sizeof (p_port->rx)); memset (&p_port->tx, 0, sizeof (p_port->tx)); p_port->tx.queue = fixed_queue_new(SIZE_MAX); p_port->rx.queue = fixed_queue_new(SIZE_MAX); }
/******************************************************************************* ** ** Function btm_init ** ** Description This function is called at BTM startup to allocate the ** control block (if using dynamic memory), and initializes the ** tracing level. It then initializes the various components of ** btm. ** ** Returns void ** *******************************************************************************/ void btm_init (void) { #if BTM_DYNAMIC_MEMORY btm_cb_ptr = (tBTM_CB *)osi_malloc(sizeof(tBTM_CB)); #endif /* #if BTM_DYNAMIC_MEMORY */ /* All fields are cleared; nonzero fields are reinitialized in appropriate function */ memset(&btm_cb, 0, sizeof(tBTM_CB)); btm_cb.page_queue = fixed_queue_new(QUEUE_SIZE_MAX); btm_cb.sec_pending_q = fixed_queue_new(QUEUE_SIZE_MAX); #if defined(BTM_INITIAL_TRACE_LEVEL) btm_cb.trace_level = BTM_INITIAL_TRACE_LEVEL; #else btm_cb.trace_level = BT_TRACE_LEVEL_NONE; #endif /* Initialize BTM component structures */ btm_inq_db_init(); /* Inquiry Database and Structures */ btm_acl_init(); /* ACL Database and Structures */ #if (SMP_INCLUDED == TRUE) btm_sec_init(BTM_SEC_MODE_SP); /* Security Manager Database and Structures */ #endif ///SMP_INCLUDED == TRUE #if BTM_SCO_INCLUDED == TRUE btm_sco_init(); /* SCO Database and Structures (If included) */ #endif btm_dev_init(); /* Device Manager Structures & HCI_Reset */ btm_lock_init(); btm_sem_init(); }
eager_reader_t *eager_reader_new( int fd_to_read, const allocator_t *allocator, size_t buffer_size, size_t max_buffer_count, const char *thread_name) { assert(fd_to_read != INVALID_FD); assert(allocator != NULL); assert(buffer_size > 0); assert(max_buffer_count > 0); assert(thread_name != NULL && *thread_name != '\0'); eager_reader_t *ret = osi_calloc(sizeof(eager_reader_t)); if (!ret) { LOG_ERROR(LOG_TAG, "%s unable to allocate memory for new eager_reader.", __func__); goto error; } ret->allocator = allocator; ret->inbound_fd = fd_to_read; ret->bytes_available_fd = eventfd(0, 0); if (ret->bytes_available_fd == INVALID_FD) { LOG_ERROR(LOG_TAG, "%s unable to create output reading semaphore.", __func__); goto error; } ret->buffer_size = buffer_size; ret->buffers = fixed_queue_new(max_buffer_count); if (!ret->buffers) { LOG_ERROR(LOG_TAG, "%s unable to create buffers queue.", __func__); goto error; } ret->inbound_read_thread = thread_new(thread_name); if (!ret->inbound_read_thread) { LOG_ERROR(LOG_TAG, "%s unable to make reading thread.", __func__); goto error; } ret->inbound_read_object = reactor_register( thread_get_reactor(ret->inbound_read_thread), fd_to_read, ret, inbound_data_waiting, NULL ); return ret; error:; eager_reader_free(ret); return NULL; }
/******************************************************************************* ** ** Function rfc_alloc_multiplexer_channel ** ** Description This function returns existing or new control block for ** the BD_ADDR. ** *******************************************************************************/ tRFC_MCB *rfc_alloc_multiplexer_channel (BD_ADDR bd_addr, BOOLEAN is_initiator) { int i, j; tRFC_MCB *p_mcb = NULL; RFCOMM_TRACE_DEBUG("rfc_alloc_multiplexer_channel: bd_addr:%02x:%02x:%02x:%02x:%02x:%02x", bd_addr[0], bd_addr[1], bd_addr[2], bd_addr[3], bd_addr[4], bd_addr[5]); RFCOMM_TRACE_DEBUG("rfc_alloc_multiplexer_channel:is_initiator:%d", is_initiator); for (i = 0; i < MAX_BD_CONNECTIONS; i++) { RFCOMM_TRACE_DEBUG("rfc_alloc_multiplexer_channel rfc_cb.port.rfc_mcb[%d].state:%d", i, rfc_cb.port.rfc_mcb[i].state); RFCOMM_TRACE_DEBUG("(rfc_cb.port.rfc_mcb[i].bd_addr:%02x:%02x:%02x:%02x:%02x:%02x", rfc_cb.port.rfc_mcb[i].bd_addr[0], rfc_cb.port.rfc_mcb[i].bd_addr[1], rfc_cb.port.rfc_mcb[i].bd_addr[2], rfc_cb.port.rfc_mcb[i].bd_addr[3], rfc_cb.port.rfc_mcb[i].bd_addr[4], rfc_cb.port.rfc_mcb[i].bd_addr[5]); if ((rfc_cb.port.rfc_mcb[i].state != RFC_MX_STATE_IDLE) && (!memcmp (rfc_cb.port.rfc_mcb[i].bd_addr, bd_addr, BD_ADDR_LEN))) { /* Multiplexer channel found do not change anything */ /* If there was an inactivity timer running stop it now */ if (rfc_cb.port.rfc_mcb[i].state == RFC_MX_STATE_CONNECTED) { rfc_timer_stop (&rfc_cb.port.rfc_mcb[i]); } RFCOMM_TRACE_DEBUG("rfc_alloc_multiplexer_channel:is_initiator:%d, found, state:%d, p_mcb:%p", is_initiator, rfc_cb.port.rfc_mcb[i].state, &rfc_cb.port.rfc_mcb[i]); return (&rfc_cb.port.rfc_mcb[i]); } } /* connection with bd_addr does not exist */ for (i = 0, j = rfc_cb.rfc.last_mux + 1; i < MAX_BD_CONNECTIONS; i++, j++) { if (j >= MAX_BD_CONNECTIONS) { j = 0; } p_mcb = &rfc_cb.port.rfc_mcb[j]; if (rfc_cb.port.rfc_mcb[j].state == RFC_MX_STATE_IDLE) { /* New multiplexer control block */ fixed_queue_free(p_mcb->cmd_q, NULL); memset (p_mcb, 0, sizeof (tRFC_MCB)); memcpy (p_mcb->bd_addr, bd_addr, BD_ADDR_LEN); RFCOMM_TRACE_DEBUG("rfc_alloc_multiplexer_channel:is_initiator:%d, create new p_mcb:%p, index:%d", is_initiator, &rfc_cb.port.rfc_mcb[j], j); p_mcb->cmd_q = fixed_queue_new(SIZE_MAX); p_mcb->is_initiator = is_initiator; rfc_timer_start (p_mcb, RFC_MCB_INIT_INACT_TIMER); rfc_cb.rfc.last_mux = (UINT8) j; return (p_mcb); } } return (NULL); }
static void btc_a2dp_sink_thread_init(UNUSED_ATTR void *context) { APPL_TRACE_EVENT("%s\n", __func__); memset(&btc_aa_snk_cb, 0, sizeof(btc_aa_snk_cb)); btc_a2dp_sink_state = BTC_A2DP_SINK_STATE_ON; btc_aa_snk_cb.RxSbcQ = fixed_queue_new(SIZE_MAX); btc_a2dp_control_init(); }
static int hci_layer_init_env(void) { command_waiting_response_t *cmd_wait_q; // The host is only allowed to send at most one command initially, // as per the Bluetooth spec, Volume 2, Part E, 4.4 (Command Flow Control) // This value can change when you get a command complete or command status event. hci_host_env.command_credits = 1; hci_host_env.command_queue = fixed_queue_new(SIZE_MAX); if (hci_host_env.command_queue) { fixed_queue_register_dequeue(hci_host_env.command_queue, event_command_ready); } else { LOG_ERROR("%s unable to create pending command queue.", __func__); return -1; } hci_host_env.packet_queue = fixed_queue_new(SIZE_MAX); if (hci_host_env.packet_queue) { fixed_queue_register_dequeue(hci_host_env.packet_queue, event_packet_ready); } else { LOG_ERROR("%s unable to create pending packet queue.", __func__); return -1; } // Init Commands waiting response list and timer cmd_wait_q = &hci_host_env.cmd_waiting_q; cmd_wait_q->timer_is_set = false; cmd_wait_q->commands_pending_response = list_new(NULL); if (!cmd_wait_q->commands_pending_response) { LOG_ERROR("%s unable to create list for commands pending response.", __func__); return -1; } pthread_mutex_init(&cmd_wait_q->commands_pending_response_lock, NULL); cmd_wait_q->command_response_timer = osi_alarm_new("cmd_rsp_to", command_timed_out, cmd_wait_q, COMMAND_PENDING_TIMEOUT); if (!cmd_wait_q->command_response_timer) { LOG_ERROR("%s unable to create command response timer.", __func__); return -1; } return 0; }
/******************************************************************************* ** ** Function avdt_scb_alloc ** ** Description Allocate a stream control block. ** ** ** Returns pointer to the scb, or NULL if none could be allocated. ** *******************************************************************************/ tAVDT_SCB *avdt_scb_alloc(tAVDT_CS *p_cs) { tAVDT_SCB *p_scb = &avdt_cb.scb[0]; int i; /* find available scb */ for (i = 0; i < AVDT_NUM_SEPS; i++, p_scb++) { if (!p_scb->allocated) { memset(p_scb, 0, sizeof(tAVDT_SCB)); p_scb->allocated = TRUE; p_scb->p_ccb = NULL; /* initialize sink as activated */ if (p_cs->tsep == AVDT_TSEP_SNK) { p_scb->sink_activated = TRUE; } memcpy(&p_scb->cs, p_cs, sizeof(tAVDT_CS)); #if AVDT_MULTIPLEXING == TRUE /* initialize fragments gueue */ p_scb->frag_q = fixed_queue_new(SIZE_MAX); if (p_cs->cfg.psc_mask & AVDT_PSC_MUX) { p_scb->cs.cfg.mux_tcid_media = avdt_ad_type_to_tcid(AVDT_CHAN_MEDIA, p_scb); #if AVDT_REPORTING == TRUE if (p_cs->cfg.psc_mask & AVDT_PSC_REPORT) { p_scb->cs.cfg.mux_tcid_report = avdt_ad_type_to_tcid(AVDT_CHAN_REPORT, p_scb); } #endif } #endif p_scb->timer_entry.param = (UINT32) p_scb; AVDT_TRACE_DEBUG("avdt_scb_alloc hdl=%d, psc_mask:0x%x\n", i + 1, p_cs->cfg.psc_mask); break; } } if (i == AVDT_NUM_SEPS) { /* out of ccbs */ p_scb = NULL; AVDT_TRACE_WARNING("Out of scbs"); } return p_scb; }
thread_t *thread_new_sized(const char *name, size_t work_queue_capacity) { assert(name != NULL); assert(work_queue_capacity != 0); thread_t *ret = osi_calloc(sizeof(thread_t)); if (!ret) goto error; ret->reactor = reactor_new(); if (!ret->reactor) goto error; ret->work_queue = fixed_queue_new(work_queue_capacity); if (!ret->work_queue) goto error; // Start is on the stack, but we use a semaphore, so it's safe struct start_arg start; start.start_sem = semaphore_new(0); if (!start.start_sem) goto error; strncpy(ret->name, name, THREAD_NAME_MAX); start.thread = ret; start.error = 0; pthread_create(&ret->pthread, NULL, run_thread, &start); semaphore_wait(start.start_sem); semaphore_free(start.start_sem); if (start.error) goto error; return ret; error:; if (ret) { fixed_queue_free(ret->work_queue, osi_free); reactor_free(ret->reactor); } osi_free(ret); return NULL; }
/******************************************************************************* ** ** Function avct_lcb_alloc ** ** Description Allocate a link control block. ** ** ** Returns pointer to the lcb, or NULL if none could be allocated. ** *******************************************************************************/ tAVCT_LCB *avct_lcb_alloc(BD_ADDR bd_addr) { tAVCT_LCB *p_lcb = &avct_cb.lcb[0]; int i; for (i = 0; i < AVCT_NUM_LINKS; i++, p_lcb++) { if (!p_lcb->allocated) { p_lcb->allocated = (UINT8)(i + 1); memcpy(p_lcb->peer_addr, bd_addr, BD_ADDR_LEN); AVCT_TRACE_DEBUG("avct_lcb_alloc %d", p_lcb->allocated); p_lcb->tx_q = fixed_queue_new(SIZE_MAX); break; } } if (i == AVCT_NUM_LINKS) { /* out of lcbs */ p_lcb = NULL; AVCT_TRACE_WARNING("Out of lcbs"); } return p_lcb; }
thread_t *thread_new(const char *name) { assert(name != NULL); // Start is on the stack, but we use a semaphore, so it's safe thread_t *ret = calloc(1, sizeof(thread_t)); if (!ret) goto error; ret->reactor = reactor_new(); if (!ret->reactor) goto error; ret->work_queue = fixed_queue_new(WORK_QUEUE_CAPACITY); if (!ret->work_queue) goto error; struct start_arg start; start.start_sem = semaphore_new(0); if (!start.start_sem) goto error; strncpy(ret->name, name, THREAD_NAME_MAX); start.thread = ret; start.error = 0; pthread_create(&ret->pthread, NULL, run_thread, &start); semaphore_wait(start.start_sem); semaphore_free(start.start_sem); if (start.error) goto error; return ret; error:; if (ret) { fixed_queue_free(ret->work_queue, free); reactor_free(ret->reactor); } free(ret); return NULL; }
/****************************************************************************** ** ** Function bte_main_boot_entry ** ** Description BTE MAIN API - Entry point for BTE chip/stack initialization ** ** Returns None ** ******************************************************************************/ int bte_main_boot_entry(bluedroid_init_done_cb_t cb) { #ifdef CONFIG_BLUEDROID_MEM_DEBUG osi_mem_dbg_init(); #endif if (gki_init()) { LOG_ERROR("%s: Init GKI Module Failure.\n", __func__); return -1; } hci = hci_layer_get_interface(); if (!hci) { LOG_ERROR("%s could not get hci layer interface.\n", __func__); return -2; } btu_hci_msg_queue = fixed_queue_new(SIZE_MAX); if (btu_hci_msg_queue == NULL) { LOG_ERROR("%s unable to allocate hci message queue.\n", __func__); return -3; } bluedroid_init_done_cb = cb; //Caution: No event dispatcher defined now in hci layer //data_dispatcher_register_default(hci->event_dispatcher, btu_hci_msg_queue); hci->set_data_queue(btu_hci_msg_queue); #if (defined(BLE_INCLUDED) && (BLE_INCLUDED == TRUE)) //bte_load_ble_conf(BTE_BLE_STACK_CONF_FILE); #endif //Enbale HCI bte_main_enable(); return 0; }
/***************************************************************************** ** ** Function BTU_StartUp ** ** Description Initializes the BTU control block. ** ** NOTE: Must be called before creating any tasks ** (RPC, BTU, HCIT, APPL, etc.) ** ** Returns void ** ******************************************************************************/ void BTU_StartUp(void) { memset (&btu_cb, 0, sizeof (tBTU_CB)); btu_cb.trace_level = HCI_INITIAL_TRACE_LEVEL; btu_bta_msg_queue = fixed_queue_new(SIZE_MAX); if (btu_bta_msg_queue == NULL) { goto error_exit; } btu_general_alarm_hash_map = hash_map_new(BTU_GENERAL_ALARM_HASH_MAP_SIZE, hash_function_pointer, NULL, (data_free_fn)osi_alarm_free, NULL); if (btu_general_alarm_hash_map == NULL) { goto error_exit; } pthread_mutex_init(&btu_general_alarm_lock, NULL); btu_general_alarm_queue = fixed_queue_new(SIZE_MAX); if (btu_general_alarm_queue == NULL) { goto error_exit; } btu_oneshot_alarm_hash_map = hash_map_new(BTU_ONESHOT_ALARM_HASH_MAP_SIZE, hash_function_pointer, NULL, (data_free_fn)osi_alarm_free, NULL); if (btu_oneshot_alarm_hash_map == NULL) { goto error_exit; } pthread_mutex_init(&btu_oneshot_alarm_lock, NULL); btu_oneshot_alarm_queue = fixed_queue_new(SIZE_MAX); if (btu_oneshot_alarm_queue == NULL) { goto error_exit; } btu_l2cap_alarm_hash_map = hash_map_new(BTU_L2CAP_ALARM_HASH_MAP_SIZE, hash_function_pointer, NULL, (data_free_fn)osi_alarm_free, NULL); if (btu_l2cap_alarm_hash_map == NULL) { goto error_exit; } pthread_mutex_init(&btu_l2cap_alarm_lock, NULL); btu_l2cap_alarm_queue = fixed_queue_new(SIZE_MAX); if (btu_l2cap_alarm_queue == NULL) { goto error_exit; } xBtuQueue = xQueueCreate(BTU_QUEUE_NUM, sizeof(BtTaskEvt_t)); xTaskCreatePinnedToCore(btu_task_thread_handler, BTU_TASK_NAME, BTU_TASK_STACK_SIZE, NULL, BTU_TASK_PRIO, &xBtuTaskHandle, 0); btu_task_post(SIG_BTU_START_UP); /* // Continue startup on bt workqueue thread. thread_post(bt_workqueue_thread, btu_task_start_up, NULL); */ return; error_exit:; LOG_ERROR("%s Unable to allocate resources for bt_workqueue", __func__); BTU_ShutDown(); }
static future_t *start_up(void) { LOG_INFO(LOG_TAG, "%s", __func__); // The host is only allowed to send at most one command initially, // as per the Bluetooth spec, Volume 2, Part E, 4.4 (Command Flow Control) // This value can change when you get a command complete or command status event. command_credits = 1; firmware_is_configured = false; pthread_mutex_init(&commands_pending_response_lock, NULL); // TODO(armansito): cutils/properties.h is only being used to pull-in runtime // settings on Android. Remove this conditional include once we have a generic // way to obtain system properties. For now, always use the default timeout on // non-Android builds. period_ms_t startup_timeout_ms = DEFAULT_STARTUP_TIMEOUT_MS; #if !defined(OS_GENERIC) // Grab the override startup timeout ms, if present. char timeout_prop[PROPERTY_VALUE_MAX]; if (!property_get("bluetooth.enable_timeout_ms", timeout_prop, STRING_VALUE_OF(DEFAULT_STARTUP_TIMEOUT_MS)) || (startup_timeout_ms = atoi(timeout_prop)) < 100) startup_timeout_ms = DEFAULT_STARTUP_TIMEOUT_MS; #endif // !defined(OS_GENERIC) startup_timer = non_repeating_timer_new(startup_timeout_ms, startup_timer_expired, NULL); if (!startup_timer) { LOG_ERROR(LOG_TAG, "%s unable to create startup timer.", __func__); goto error; } // Make sure we run in a bounded amount of time non_repeating_timer_restart(startup_timer); epilog_timer = non_repeating_timer_new(EPILOG_TIMEOUT_MS, epilog_timer_expired, NULL); if (!epilog_timer) { LOG_ERROR(LOG_TAG, "%s unable to create epilog timer.", __func__); goto error; } command_response_timer = non_repeating_timer_new(COMMAND_PENDING_TIMEOUT, command_timed_out, NULL); if (!command_response_timer) { LOG_ERROR(LOG_TAG, "%s unable to create command response timer.", __func__); goto error; } command_queue = fixed_queue_new(SIZE_MAX); if (!command_queue) { LOG_ERROR(LOG_TAG, "%s unable to create pending command queue.", __func__); goto error; } packet_queue = fixed_queue_new(SIZE_MAX); if (!packet_queue) { LOG_ERROR(LOG_TAG, "%s unable to create pending packet queue.", __func__); goto error; } thread = thread_new("hci_thread"); if (!thread) { LOG_ERROR(LOG_TAG, "%s unable to create thread.", __func__); goto error; } commands_pending_response = list_new(NULL); if (!commands_pending_response) { LOG_ERROR(LOG_TAG, "%s unable to create list for commands pending response.", __func__); goto error; } memset(incoming_packets, 0, sizeof(incoming_packets)); packet_fragmenter->init(&packet_fragmenter_callbacks); fixed_queue_register_dequeue(command_queue, thread_get_reactor(thread), event_command_ready, NULL); fixed_queue_register_dequeue(packet_queue, thread_get_reactor(thread), event_packet_ready, NULL); vendor->open(btif_local_bd_addr.address, &interface); hal->init(&hal_callbacks, thread); low_power_manager->init(thread); vendor->set_callback(VENDOR_CONFIGURE_FIRMWARE, firmware_config_callback); vendor->set_callback(VENDOR_CONFIGURE_SCO, sco_config_callback); vendor->set_callback(VENDOR_DO_EPILOG, epilog_finished_callback); if (!hci_inject->open(&interface)) { // TODO(sharvil): gracefully propagate failures from this layer. } int power_state = BT_VND_PWR_OFF; #if (defined (BT_CLEAN_TURN_ON_DISABLED) && BT_CLEAN_TURN_ON_DISABLED == TRUE) LOG_WARN(LOG_TAG, "%s not turning off the chip before turning on.", __func__); // So apparently this hack was needed in the past because a Wingray kernel driver // didn't handle power off commands in a powered off state correctly. // The comment in the old code said the workaround should be removed when the // problem was fixed. Sadly, I have no idea if said bug was fixed or if said // kernel is still in use, so we must leave this here for posterity. #sadpanda #else // cycle power on the chip to ensure it has been reset vendor->send_command(VENDOR_CHIP_POWER_CONTROL, &power_state); #endif power_state = BT_VND_PWR_ON; vendor->send_command(VENDOR_CHIP_POWER_CONTROL, &power_state); startup_future = future_new(); LOG_DEBUG(LOG_TAG, "%s starting async portion", __func__); thread_post(thread, event_finish_startup, NULL); return startup_future; error:; shut_down(); // returns NULL so no need to wait for it return future_new_immediate(FUTURE_FAIL); }