Ejemplo n.º 1
0
void btu_task_start_up(UNUSED_ATTR void *context) {
  BT_TRACE(TRACE_LAYER_BTU, TRACE_TYPE_API,
      "btu_task pending for preload complete event");

  LOG_INFO(LOG_TAG, "Bluetooth chip preload is complete");

  BT_TRACE(TRACE_LAYER_BTU, TRACE_TYPE_API,
      "btu_task received preload complete event");

  /* Initialize the mandatory core stack control blocks
     (BTU, BTM, L2CAP, and SDP)
   */
  btu_init_core();

  /* Initialize any optional stack components */
  BTE_InitStack();

  bta_sys_init();

  /* Initialise platform trace levels at this point as BTE_InitStack() and bta_sys_init()
   * reset the control blocks and preset the trace level with XXX_INITIAL_TRACE_LEVEL
   */
#if ( BT_USE_TRACES==TRUE )
  module_init(get_module(BTE_LOGMSG_MODULE));
#endif

  // Inform the bt jni thread initialization is ok.
  btif_transfer_context(btif_init_ok, 0, NULL, 0, NULL);

  fixed_queue_register_dequeue(btu_bta_msg_queue,
      thread_get_reactor(bt_workqueue_thread),
      btu_bta_msg_ready,
      NULL);

  fixed_queue_register_dequeue(btu_hci_msg_queue,
      thread_get_reactor(bt_workqueue_thread),
      btu_hci_msg_ready,
      NULL);

  fixed_queue_register_dequeue(btu_general_alarm_queue,
      thread_get_reactor(bt_workqueue_thread),
      btu_general_alarm_ready,
      NULL);

  fixed_queue_register_dequeue(btu_oneshot_alarm_queue,
      thread_get_reactor(bt_workqueue_thread),
      btu_oneshot_alarm_ready,
      NULL);

  fixed_queue_register_dequeue(btu_l2cap_alarm_queue,
      thread_get_reactor(bt_workqueue_thread),
      btu_l2cap_alarm_ready,
      NULL);
}
Ejemplo n.º 2
0
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;
}
Ejemplo n.º 3
0
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);
}