15738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************
25738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *
35738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  Copyright (C) 2009-2012 Broadcom Corporation
45738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *
55738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  Licensed under the Apache License, Version 2.0 (the "License");
65738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  you may not use this file except in compliance with the License.
75738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  You may obtain a copy of the License at:
85738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *
95738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  http://www.apache.org/licenses/LICENSE-2.0
105738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *
115738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  Unless required by applicable law or agreed to in writing, software
125738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  distributed under the License is distributed on an "AS IS" BASIS,
135738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
145738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  See the License for the specific language governing permissions and
155738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  limitations under the License.
165738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *
175738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project ******************************************************************************/
185738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
195738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************
205738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *
215738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  Filename:      bt_hci_bdroid.c
225738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *
235738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  Description:   Bluedroid Bluetooth Host/Controller interface library
245738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *                 implementation
255738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *
265738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project ******************************************************************************/
275738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
285738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#define LOG_TAG "bt_hci_bdroid"
295738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
30c4e0e049e27622f01e93a4ac6beaec60d72d2364Sharvil Nanavati#include <assert.h>
315738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#include <utils/Log.h>
32dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati
33dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati#include "btsnoop.h"
345738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#include "bt_hci_bdroid.h"
35dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati#include "bt_utils.h"
365738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#include "bt_vendor_lib.h"
375738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#include "hci.h"
38dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati#include "osi.h"
39dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati#include "thread.h"
405738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#include "userial.h"
41dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati#include "utils.h"
42f3b23f231a39176ea371c4da717e084b3d7cc15aSharvil Nanavati#include "vendor.h"
435738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
445738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#ifndef BTHC_DBG
455738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#define BTHC_DBG FALSE
465738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif
475738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
485738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (BTHC_DBG == TRUE)
495738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#define BTHCDBG(param, ...) {ALOGD(param, ## __VA_ARGS__);}
505738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#else
515738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#define BTHCDBG(param, ...) {}
525738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif
535738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
5467e4077c23bb9cc045885ae01cc83b38faecb71bYK Jeffrey Chao/* Vendor epilog process timeout period  */
55dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavatistatic const uint32_t EPILOG_TIMEOUT_MS = 3000;
5667e4077c23bb9cc045885ae01cc83b38faecb71bYK Jeffrey Chao
575738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************
585738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**  Externs
595738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project******************************************************************************/
605738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
615738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectextern int num_hci_cmd_pkts;
625738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectvoid lpm_init(void);
635738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectvoid lpm_cleanup(void);
645738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectvoid lpm_enable(uint8_t turn_on);
655738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectvoid lpm_wake_deassert(void);
665738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectvoid lpm_allow_bt_device_sleep(void);
675738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectvoid lpm_wake_assert(void);
685738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectvoid init_vnd_if(unsigned char *local_bdaddr);
695738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
705738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************
715738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**  Variables
725738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project******************************************************************************/
735738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
745738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectbt_hc_callbacks_t *bt_hc_cbacks = NULL;
755738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source ProjecttHCI_IF *p_hci_if;
76dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavativolatile bool fwcfg_acked;
776c25e796a4d661ef76e9b6af253bbbfbae46a344Chris Manton// Cleanup state indication.
786c25e796a4d661ef76e9b6af253bbbfbae46a344Chris Mantonvolatile bool has_cleaned_up = false;
795738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
805738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************
815738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**  Local type definitions
825738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project******************************************************************************/
835738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
845738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/* Host/Controller lib thread control block */
855738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projecttypedef struct
865738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
87dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati    thread_t        *worker_thread;
887be309d0bd3296b37f2a16bf7cf8323f2658b3bdSharvil Nanavati    pthread_mutex_t worker_thread_lock;
89dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati    bool            epilog_timer_created;
9067e4077c23bb9cc045885ae01cc83b38faecb71bYK Jeffrey Chao    timer_t         epilog_timer_id;
915738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} bt_hc_cb_t;
925738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
935738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************
945738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**  Static Variables
955738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project******************************************************************************/
965738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
975738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectstatic bt_hc_cb_t hc_cb;
98dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavatistatic bool tx_cmd_pkts_pending = false;
99dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavatistatic BUFFER_Q tx_q;
1005738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1015738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************
1025738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**  Functions
1035738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project******************************************************************************/
1045738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
105dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavatistatic void event_preload(UNUSED_ATTR void *context) {
106dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati  userial_open(USERIAL_PORT_1);
107dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati  vendor_send_command(BT_VND_OP_FW_CFG, NULL);
108dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati}
109dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati
110dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavatistatic void event_postload(UNUSED_ATTR void *context) {
111dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati  /* Start from SCO related H/W configuration, if SCO configuration
112dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati   * is required. Then, follow with reading requests of getting
113dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati   * ACL data length for both BR/EDR and LE.
114dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati   */
115dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati  int result = vendor_send_command(BT_VND_OP_SCO_CFG, NULL);
116dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati  if (result == -1)
117dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati    p_hci_if->get_acl_max_len();
118dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati}
1193f9fbe74c1d6e774d3f21275515c7b895715aec5Sharvil Nanavati
120dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavatistatic void event_tx(UNUSED_ATTR void *context) {
121dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati  /*
122dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati   *  We will go through every packets in the tx queue.
123dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati   *  Fine to clear tx_cmd_pkts_pending.
124dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati   */
125dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati  tx_cmd_pkts_pending = false;
126dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati  HC_BT_HDR *sending_msg_que[64];
127dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati  size_t sending_msg_count = 0;
128dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati  int sending_hci_cmd_pkts_count = 0;
129dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati  utils_lock();
130dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati  HC_BT_HDR *p_next_msg = tx_q.p_first;
131dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati  while (p_next_msg && sending_msg_count < ARRAY_SIZE(sending_msg_que))
132dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati  {
133dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati    if ((p_next_msg->event & MSG_EVT_MASK)==MSG_STACK_TO_HC_HCI_CMD)
134dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati    {
135dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati      /*
136dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati       *  if we have used up controller's outstanding HCI command
137dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati       *  credits (normally is 1), skip all HCI command packets in
138dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati       *  the queue.
139dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati       *  The pending command packets will be sent once controller
140dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati       *  gives back us credits through CommandCompleteEvent or
141dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati       *  CommandStatusEvent.
142dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati       */
143dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati      if (tx_cmd_pkts_pending ||
144dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati          (sending_hci_cmd_pkts_count >= num_hci_cmd_pkts))
145dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati      {
146dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati        tx_cmd_pkts_pending = true;
147dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati        p_next_msg = utils_getnext(p_next_msg);
148dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati        continue;
149dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati      }
150dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati      sending_hci_cmd_pkts_count++;
151dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati    }
152dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati
153dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati    HC_BT_HDR *p_msg = p_next_msg;
154dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati    p_next_msg = utils_getnext(p_msg);
155dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati    utils_remove_from_queue_unlocked(&tx_q, p_msg);
156dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati    sending_msg_que[sending_msg_count++] = p_msg;
157dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati  }
158dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati  utils_unlock();
159dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati  for(size_t i = 0; i < sending_msg_count; i++)
160dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati    p_hci_if->send(sending_msg_que[i]);
161dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati  if (tx_cmd_pkts_pending)
162dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati    BTHCDBG("Used up Tx Cmd credits");
163dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati}
164dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati
165dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavatistatic void event_rx(UNUSED_ATTR void *context) {
166dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati#ifndef HCI_USE_MCT
167dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati  p_hci_if->rcv();
168dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati
169dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati  if (tx_cmd_pkts_pending && num_hci_cmd_pkts > 0) {
170dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati    // Got HCI Cmd credits from controller. Send whatever data
171dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati    // we have in our tx queue. We can call |event_tx| directly
172dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati    // here since we're already on the worker thread.
173dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati    event_tx(NULL);
174dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati  }
175dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati#endif
176dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati}
177dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati
178dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavatistatic void event_lpm_enable(UNUSED_ATTR void *context) {
179dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati  lpm_enable(true);
180dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati}
181dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati
182dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavatistatic void event_lpm_disable(UNUSED_ATTR void *context) {
183dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati  lpm_enable(false);
184dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati}
185dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati
186dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavatistatic void event_lpm_wake_device(UNUSED_ATTR void *context) {
187dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati  lpm_wake_assert();
188dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati}
189dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati
190dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavatistatic void event_lpm_allow_sleep(UNUSED_ATTR void *context) {
191dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati  lpm_allow_bt_device_sleep();
192dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati}
193dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati
194dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavatistatic void event_lpm_idle_timeout(UNUSED_ATTR void *context) {
195dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati  lpm_wake_deassert();
196dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati}
197dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati
198dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavatistatic void event_epilog(UNUSED_ATTR void *context) {
199dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati  vendor_send_command(BT_VND_OP_EPILOG, NULL);
200dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati}
201dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati
202dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavatistatic void event_tx_cmd(void *msg) {
203dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati  HC_BT_HDR *p_msg = (HC_BT_HDR *)msg;
204dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati
205dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati  BTHCDBG("%s: p_msg: %p, event: 0x%x", __func__, p_msg, p_msg->event);
206dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati
207dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati  int event = p_msg->event & MSG_EVT_MASK;
208dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati  int sub_event = p_msg->event & MSG_SUB_EVT_MASK;
209dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati  if (event == MSG_CTRL_TO_HC_CMD && sub_event == BT_HC_AUDIO_STATE) {
210dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati    vendor_send_command(BT_VND_OP_SET_AUDIO_STATE, p_msg->data);
211dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati  } else {
212dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati    ALOGW("%s (event: 0x%x, sub_event: 0x%x) not supported", __func__, event, sub_event);
213dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati  }
214dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati
215dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati  bt_hc_cbacks->dealloc(msg);
216dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati}
217dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati
218dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavativoid bthc_rx_ready(void) {
2197be309d0bd3296b37f2a16bf7cf8323f2658b3bdSharvil Nanavati  pthread_mutex_lock(&hc_cb.worker_thread_lock);
2207be309d0bd3296b37f2a16bf7cf8323f2658b3bdSharvil Nanavati
2217be309d0bd3296b37f2a16bf7cf8323f2658b3bdSharvil Nanavati  if (hc_cb.worker_thread)
2227be309d0bd3296b37f2a16bf7cf8323f2658b3bdSharvil Nanavati    thread_post(hc_cb.worker_thread, event_rx, NULL);
2237be309d0bd3296b37f2a16bf7cf8323f2658b3bdSharvil Nanavati
2247be309d0bd3296b37f2a16bf7cf8323f2658b3bdSharvil Nanavati  pthread_mutex_unlock(&hc_cb.worker_thread_lock);
225dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati}
226dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati
227dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavativoid bthc_tx(HC_BT_HDR *buf) {
2287be309d0bd3296b37f2a16bf7cf8323f2658b3bdSharvil Nanavati  pthread_mutex_lock(&hc_cb.worker_thread_lock);
2297be309d0bd3296b37f2a16bf7cf8323f2658b3bdSharvil Nanavati
2307be309d0bd3296b37f2a16bf7cf8323f2658b3bdSharvil Nanavati  if (hc_cb.worker_thread) {
2317be309d0bd3296b37f2a16bf7cf8323f2658b3bdSharvil Nanavati    if (buf)
2327be309d0bd3296b37f2a16bf7cf8323f2658b3bdSharvil Nanavati      utils_enqueue(&tx_q, buf);
2337be309d0bd3296b37f2a16bf7cf8323f2658b3bdSharvil Nanavati    thread_post(hc_cb.worker_thread, event_tx, NULL);
2347be309d0bd3296b37f2a16bf7cf8323f2658b3bdSharvil Nanavati  }
2357be309d0bd3296b37f2a16bf7cf8323f2658b3bdSharvil Nanavati
2367be309d0bd3296b37f2a16bf7cf8323f2658b3bdSharvil Nanavati  pthread_mutex_unlock(&hc_cb.worker_thread_lock);
237dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati}
238dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati
239dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavativoid bthc_idle_timeout(void) {
2407be309d0bd3296b37f2a16bf7cf8323f2658b3bdSharvil Nanavati  pthread_mutex_lock(&hc_cb.worker_thread_lock);
2417be309d0bd3296b37f2a16bf7cf8323f2658b3bdSharvil Nanavati
2427be309d0bd3296b37f2a16bf7cf8323f2658b3bdSharvil Nanavati  if (hc_cb.worker_thread)
2437be309d0bd3296b37f2a16bf7cf8323f2658b3bdSharvil Nanavati    thread_post(hc_cb.worker_thread, event_lpm_idle_timeout, NULL);
2447be309d0bd3296b37f2a16bf7cf8323f2658b3bdSharvil Nanavati
2457be309d0bd3296b37f2a16bf7cf8323f2658b3bdSharvil Nanavati  pthread_mutex_unlock(&hc_cb.worker_thread_lock);
2465738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
2475738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
24867e4077c23bb9cc045885ae01cc83b38faecb71bYK Jeffrey Chao/*******************************************************************************
24967e4077c23bb9cc045885ae01cc83b38faecb71bYK Jeffrey Chao**
25067e4077c23bb9cc045885ae01cc83b38faecb71bYK Jeffrey Chao** Function        epilog_wait_timeout
25167e4077c23bb9cc045885ae01cc83b38faecb71bYK Jeffrey Chao**
25267e4077c23bb9cc045885ae01cc83b38faecb71bYK Jeffrey Chao** Description     Timeout thread of epilog watchdog timer
25367e4077c23bb9cc045885ae01cc83b38faecb71bYK Jeffrey Chao**
25467e4077c23bb9cc045885ae01cc83b38faecb71bYK Jeffrey Chao** Returns         None
25567e4077c23bb9cc045885ae01cc83b38faecb71bYK Jeffrey Chao**
25667e4077c23bb9cc045885ae01cc83b38faecb71bYK Jeffrey Chao*******************************************************************************/
257dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavatistatic void epilog_wait_timeout(UNUSED_ATTR union sigval arg)
25867e4077c23bb9cc045885ae01cc83b38faecb71bYK Jeffrey Chao{
25967e4077c23bb9cc045885ae01cc83b38faecb71bYK Jeffrey Chao    ALOGI("...epilog_wait_timeout...");
2607be309d0bd3296b37f2a16bf7cf8323f2658b3bdSharvil Nanavati
261dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati    thread_free(hc_cb.worker_thread);
2627be309d0bd3296b37f2a16bf7cf8323f2658b3bdSharvil Nanavati
2637be309d0bd3296b37f2a16bf7cf8323f2658b3bdSharvil Nanavati    pthread_mutex_lock(&hc_cb.worker_thread_lock);
264dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati    hc_cb.worker_thread = NULL;
2657be309d0bd3296b37f2a16bf7cf8323f2658b3bdSharvil Nanavati    pthread_mutex_unlock(&hc_cb.worker_thread_lock);
26667e4077c23bb9cc045885ae01cc83b38faecb71bYK Jeffrey Chao}
26767e4077c23bb9cc045885ae01cc83b38faecb71bYK Jeffrey Chao
26867e4077c23bb9cc045885ae01cc83b38faecb71bYK Jeffrey Chao/*******************************************************************************
26967e4077c23bb9cc045885ae01cc83b38faecb71bYK Jeffrey Chao**
27067e4077c23bb9cc045885ae01cc83b38faecb71bYK Jeffrey Chao** Function        epilog_wait_timer
27167e4077c23bb9cc045885ae01cc83b38faecb71bYK Jeffrey Chao**
27267e4077c23bb9cc045885ae01cc83b38faecb71bYK Jeffrey Chao** Description     Launch epilog watchdog timer
27367e4077c23bb9cc045885ae01cc83b38faecb71bYK Jeffrey Chao**
27467e4077c23bb9cc045885ae01cc83b38faecb71bYK Jeffrey Chao** Returns         None
27567e4077c23bb9cc045885ae01cc83b38faecb71bYK Jeffrey Chao**
27667e4077c23bb9cc045885ae01cc83b38faecb71bYK Jeffrey Chao*******************************************************************************/
27767e4077c23bb9cc045885ae01cc83b38faecb71bYK Jeffrey Chaostatic void epilog_wait_timer(void)
27867e4077c23bb9cc045885ae01cc83b38faecb71bYK Jeffrey Chao{
27967e4077c23bb9cc045885ae01cc83b38faecb71bYK Jeffrey Chao    int status;
28067e4077c23bb9cc045885ae01cc83b38faecb71bYK Jeffrey Chao    struct itimerspec ts;
28167e4077c23bb9cc045885ae01cc83b38faecb71bYK Jeffrey Chao    struct sigevent se;
28267e4077c23bb9cc045885ae01cc83b38faecb71bYK Jeffrey Chao    uint32_t timeout_ms = EPILOG_TIMEOUT_MS;
28367e4077c23bb9cc045885ae01cc83b38faecb71bYK Jeffrey Chao
28467e4077c23bb9cc045885ae01cc83b38faecb71bYK Jeffrey Chao    se.sigev_notify = SIGEV_THREAD;
28567e4077c23bb9cc045885ae01cc83b38faecb71bYK Jeffrey Chao    se.sigev_value.sival_ptr = &hc_cb.epilog_timer_id;
28667e4077c23bb9cc045885ae01cc83b38faecb71bYK Jeffrey Chao    se.sigev_notify_function = epilog_wait_timeout;
28767e4077c23bb9cc045885ae01cc83b38faecb71bYK Jeffrey Chao    se.sigev_notify_attributes = NULL;
28867e4077c23bb9cc045885ae01cc83b38faecb71bYK Jeffrey Chao
28967e4077c23bb9cc045885ae01cc83b38faecb71bYK Jeffrey Chao    status = timer_create(CLOCK_MONOTONIC, &se, &hc_cb.epilog_timer_id);
29067e4077c23bb9cc045885ae01cc83b38faecb71bYK Jeffrey Chao
29167e4077c23bb9cc045885ae01cc83b38faecb71bYK Jeffrey Chao    if (status == 0)
29267e4077c23bb9cc045885ae01cc83b38faecb71bYK Jeffrey Chao    {
293dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati        hc_cb.epilog_timer_created = true;
29467e4077c23bb9cc045885ae01cc83b38faecb71bYK Jeffrey Chao        ts.it_value.tv_sec = timeout_ms/1000;
29567e4077c23bb9cc045885ae01cc83b38faecb71bYK Jeffrey Chao        ts.it_value.tv_nsec = 1000000*(timeout_ms%1000);
29667e4077c23bb9cc045885ae01cc83b38faecb71bYK Jeffrey Chao        ts.it_interval.tv_sec = 0;
29767e4077c23bb9cc045885ae01cc83b38faecb71bYK Jeffrey Chao        ts.it_interval.tv_nsec = 0;
29867e4077c23bb9cc045885ae01cc83b38faecb71bYK Jeffrey Chao
29967e4077c23bb9cc045885ae01cc83b38faecb71bYK Jeffrey Chao        status = timer_settime(hc_cb.epilog_timer_id, 0, &ts, 0);
30067e4077c23bb9cc045885ae01cc83b38faecb71bYK Jeffrey Chao        if (status == -1)
30167e4077c23bb9cc045885ae01cc83b38faecb71bYK Jeffrey Chao            ALOGE("Failed to fire epilog watchdog timer");
30267e4077c23bb9cc045885ae01cc83b38faecb71bYK Jeffrey Chao    }
30367e4077c23bb9cc045885ae01cc83b38faecb71bYK Jeffrey Chao    else
30467e4077c23bb9cc045885ae01cc83b38faecb71bYK Jeffrey Chao    {
30567e4077c23bb9cc045885ae01cc83b38faecb71bYK Jeffrey Chao        ALOGE("Failed to create epilog watchdog timer");
306dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati        hc_cb.epilog_timer_created = false;
30767e4077c23bb9cc045885ae01cc83b38faecb71bYK Jeffrey Chao    }
30867e4077c23bb9cc045885ae01cc83b38faecb71bYK Jeffrey Chao}
30967e4077c23bb9cc045885ae01cc83b38faecb71bYK Jeffrey Chao
3105738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*****************************************************************************
3115738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
3125738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**   BLUETOOTH HOST/CONTROLLER INTERFACE LIBRARY FUNCTIONS
3135738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
3145738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project*****************************************************************************/
3155738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3165738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectstatic int init(const bt_hc_callbacks_t* p_cb, unsigned char *local_bdaddr)
3175738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
318dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati    int result;
3195738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3205738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    ALOGI("init");
3215738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3225738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if (p_cb == NULL)
3235738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
3245738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        ALOGE("init failed with no user callbacks!");
3255738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        return BT_HC_STATUS_FAIL;
3265738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
3275738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
328dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati    hc_cb.epilog_timer_created = false;
329dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati    fwcfg_acked = false;
3306c25e796a4d661ef76e9b6af253bbbfbae46a344Chris Manton    has_cleaned_up = false;
33167e4077c23bb9cc045885ae01cc83b38faecb71bYK Jeffrey Chao
3327be309d0bd3296b37f2a16bf7cf8323f2658b3bdSharvil Nanavati    pthread_mutex_init(&hc_cb.worker_thread_lock, NULL);
3337be309d0bd3296b37f2a16bf7cf8323f2658b3bdSharvil Nanavati
3345738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    /* store reference to user callbacks */
3355738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    bt_hc_cbacks = (bt_hc_callbacks_t *) p_cb;
3365738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
337f3b23f231a39176ea371c4da717e084b3d7cc15aSharvil Nanavati    vendor_open(local_bdaddr);
3385738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3395738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    utils_init();
3405738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#ifdef HCI_USE_MCT
3415738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    extern tHCI_IF hci_mct_func_table;
3425738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    p_hci_if = &hci_mct_func_table;
3435738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#else
3445738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    extern tHCI_IF hci_h4_func_table;
3455738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    p_hci_if = &hci_h4_func_table;
3465738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif
3475738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3485738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    p_hci_if->init();
3495738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3505738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    userial_init();
3515738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    lpm_init();
3525738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3535738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    utils_queue_init(&tx_q);
3545738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
355dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati    if (hc_cb.worker_thread)
3565738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
3575738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        ALOGW("init has been called repeatedly without calling cleanup ?");
3585738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
3595738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3603eae42f2a383adaaf83336dc4c92afd2de2c4112Mattias Agren    // Set prio here and let hci worker thread inherit prio
3613eae42f2a383adaaf83336dc4c92afd2de2c4112Mattias Agren    // remove once new thread api (thread_set_priority() ?)
3623eae42f2a383adaaf83336dc4c92afd2de2c4112Mattias Agren    // can switch prio
3633eae42f2a383adaaf83336dc4c92afd2de2c4112Mattias Agren    raise_priority_a2dp(TASK_HIGH_HCI_WORKER);
3643eae42f2a383adaaf83336dc4c92afd2de2c4112Mattias Agren
365dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati    hc_cb.worker_thread = thread_new("bt_hc_worker");
366dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati    if (!hc_cb.worker_thread) {
367dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati        ALOGE("%s unable to create worker thread.", __func__);
3685738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        return BT_HC_STATUS_FAIL;
3695738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
3705738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3715738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    return BT_HC_STATUS_SUCCESS;
3725738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
3735738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3745738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3755738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/** Chip power control */
3765738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectstatic void set_power(bt_hc_chip_power_state_t state)
3775738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
3785738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    int pwr_state;
3795738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3805738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    BTHCDBG("set_power %d", state);
3815738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3825738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    /* Calling vendor-specific part */
3835738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    pwr_state = (state == BT_HC_CHIP_PWR_ON) ? BT_VND_PWR_ON : BT_VND_PWR_OFF;
3845738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
385f3b23f231a39176ea371c4da717e084b3d7cc15aSharvil Nanavati    vendor_send_command(BT_VND_OP_POWER_CTRL, &pwr_state);
3865738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
3875738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3885738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3895738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/** Configure low power mode wake state */
3905738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectstatic int lpm(bt_hc_low_power_event_t event)
3915738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
3925738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    switch (event)
3935738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
3945738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        case BT_HC_LPM_DISABLE:
395dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati            thread_post(hc_cb.worker_thread, event_lpm_disable, NULL);
3965738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            break;
3975738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3985738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        case BT_HC_LPM_ENABLE:
399dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati            thread_post(hc_cb.worker_thread, event_lpm_enable, NULL);
4005738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            break;
4015738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
4025738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        case BT_HC_LPM_WAKE_ASSERT:
403dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati            thread_post(hc_cb.worker_thread, event_lpm_wake_device, NULL);
4045738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            break;
4055738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
4065738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        case BT_HC_LPM_WAKE_DEASSERT:
407dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati            thread_post(hc_cb.worker_thread, event_lpm_allow_sleep, NULL);
4085738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            break;
4095738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
410dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati    return BT_HC_STATUS_SUCCESS;
4115738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
4125738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
4135738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
4145cd8bff2dd0337cb52bf48f312e3d2d55a8882fbMike J. Chen/** Called prior to stack initialization */
415dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavatistatic void preload(UNUSED_ATTR TRANSAC transac) {
416dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati  BTHCDBG("preload");
417dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati  thread_post(hc_cb.worker_thread, event_preload, NULL);
4185738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
4195738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
4205738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/** Called post stack initialization */
421dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavatistatic void postload(UNUSED_ATTR TRANSAC transac) {
422dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati  BTHCDBG("postload");
423dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati  thread_post(hc_cb.worker_thread, event_postload, NULL);
4245738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
4255738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
4265738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/** Transmit frame */
427dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavatistatic int transmit_buf(TRANSAC transac, UNUSED_ATTR char *p_buf, UNUSED_ATTR int len) {
428dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati  bthc_tx((HC_BT_HDR *)transac);
429dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati  return BT_HC_STATUS_SUCCESS;
4305738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
4315738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
4325738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/** Controls HCI logging on/off */
433311e88dd46311534c6fd1a25ec9c5c1da6d55dedAndre Eisenbachstatic int logging(bt_hc_logging_state_t state, char *p_path, bool save_existing) {
434dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati  BTHCDBG("logging %d", state);
4355738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
436dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati  if (state != BT_HC_LOGGING_ON)
437dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati    btsnoop_close();
438dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati  else if (p_path != NULL)
439311e88dd46311534c6fd1a25ec9c5c1da6d55dedAndre Eisenbach    btsnoop_open(p_path, save_existing);
4405738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
441dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati  return BT_HC_STATUS_SUCCESS;
4425738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
4435738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
44466432dcffe211e317d35978283a04a96d5620bdfMatthew Xie/** sends command HC controller to configure platform specific behaviour */
445dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavatistatic int tx_hc_cmd(TRANSAC transac, char *p_buf, int len) {
446dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati  BTHCDBG("tx_hc_cmd: transac %p", transac);
447dd29f036a8cde94b3c296fb08ee3e9b2d65c15e0Svetoslav Ganov
448dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati  if (!transac)
449dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati    return BT_HC_STATUS_FAIL;
45066432dcffe211e317d35978283a04a96d5620bdfMatthew Xie
451dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati  thread_post(hc_cb.worker_thread, event_tx_cmd, transac);
452dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati  return BT_HC_STATUS_SUCCESS;
45366432dcffe211e317d35978283a04a96d5620bdfMatthew Xie}
4545738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
4556c25e796a4d661ef76e9b6af253bbbfbae46a344Chris Manton// Closes the interface.
4566c25e796a4d661ef76e9b6af253bbbfbae46a344Chris Manton// This routine is not thread safe.
4576c25e796a4d661ef76e9b6af253bbbfbae46a344Chris Mantonstatic void cleanup(void)
4585738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
4596c25e796a4d661ef76e9b6af253bbbfbae46a344Chris Manton    if (has_cleaned_up) {
4606c25e796a4d661ef76e9b6af253bbbfbae46a344Chris Manton        ALOGW("%s Already cleaned up for this session\n", __func__);
4616c25e796a4d661ef76e9b6af253bbbfbae46a344Chris Manton        return;
4626c25e796a4d661ef76e9b6af253bbbfbae46a344Chris Manton    }
4636c25e796a4d661ef76e9b6af253bbbfbae46a344Chris Manton
4645738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    BTHCDBG("cleanup");
4655738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
466dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati    if (hc_cb.worker_thread)
4675738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
468dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati        if (fwcfg_acked)
46948ebe2c6928d8fd4dc97c8adb138c3440714dc89YK Jeffrey Chao        {
47048ebe2c6928d8fd4dc97c8adb138c3440714dc89YK Jeffrey Chao            epilog_wait_timer();
47111aa94d9988464aae233fae303f614ca48fcc834Chris Manton            // Stop reading thread
47211aa94d9988464aae233fae303f614ca48fcc834Chris Manton            userial_close_reader();
47311aa94d9988464aae233fae303f614ca48fcc834Chris Manton
474dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati            thread_post(hc_cb.worker_thread, event_epilog, NULL);
47548ebe2c6928d8fd4dc97c8adb138c3440714dc89YK Jeffrey Chao        }
476dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati        thread_free(hc_cb.worker_thread);
4777be309d0bd3296b37f2a16bf7cf8323f2658b3bdSharvil Nanavati
4787be309d0bd3296b37f2a16bf7cf8323f2658b3bdSharvil Nanavati        pthread_mutex_lock(&hc_cb.worker_thread_lock);
479dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati        hc_cb.worker_thread = NULL;
4807be309d0bd3296b37f2a16bf7cf8323f2658b3bdSharvil Nanavati        pthread_mutex_unlock(&hc_cb.worker_thread_lock);
48167e4077c23bb9cc045885ae01cc83b38faecb71bYK Jeffrey Chao
482dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati        if (hc_cb.epilog_timer_created)
48367e4077c23bb9cc045885ae01cc83b38faecb71bYK Jeffrey Chao        {
48467e4077c23bb9cc045885ae01cc83b38faecb71bYK Jeffrey Chao            timer_delete(hc_cb.epilog_timer_id);
485dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati            hc_cb.epilog_timer_created = false;
48667e4077c23bb9cc045885ae01cc83b38faecb71bYK Jeffrey Chao        }
4875738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
48811aa94d9988464aae233fae303f614ca48fcc834Chris Manton    BTHCDBG("%s Finalizing cleanup\n", __func__);
4895738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
4905738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    lpm_cleanup();
4915738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    userial_close();
4925738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    p_hci_if->cleanup();
4935738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    utils_cleanup();
4945738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
495f3b23f231a39176ea371c4da717e084b3d7cc15aSharvil Nanavati    set_power(BT_VND_PWR_OFF);
496f3b23f231a39176ea371c4da717e084b3d7cc15aSharvil Nanavati    vendor_close();
4975738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
4987be309d0bd3296b37f2a16bf7cf8323f2658b3bdSharvil Nanavati    pthread_mutex_destroy(&hc_cb.worker_thread_lock);
4997be309d0bd3296b37f2a16bf7cf8323f2658b3bdSharvil Nanavati
500dd28edb310906c63ba4535ccd02f3ca4d496f021Sharvil Nanavati    fwcfg_acked = false;
5015738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    bt_hc_cbacks = NULL;
5026c25e796a4d661ef76e9b6af253bbbfbae46a344Chris Manton    has_cleaned_up = true;
5035738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
5045738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
5055738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectstatic const bt_hc_interface_t bluetoothHCLibInterface = {
5065738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    sizeof(bt_hc_interface_t),
5075738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    init,
5085738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    set_power,
5095738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    lpm,
5105738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    preload,
5115738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    postload,
5125738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    transmit_buf,
5135738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    logging,
51466432dcffe211e317d35978283a04a96d5620bdfMatthew Xie    cleanup,
51566432dcffe211e317d35978283a04a96d5620bdfMatthew Xie    tx_hc_cmd,
5165738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project};
5175738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
5185738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
5195738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
5205738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Function        bt_hc_get_interface
5215738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
5225738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Description     Caller calls this function to get API instance
5235738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
5245738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Returns         API table
5255738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
5265738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project*******************************************************************************/
5275738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectconst bt_hc_interface_t *bt_hc_get_interface(void)
5285738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
5295738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    return &bluetoothHCLibInterface;
5305738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
531