Home | History | Annotate | Download | only in src
      1 /******************************************************************************
      2  *
      3  *  Copyright (C) 2014 Google, Inc.
      4  *
      5  *  Licensed under the Apache License, Version 2.0 (the "License");
      6  *  you may not use this file except in compliance with the License.
      7  *  You may obtain a copy of the License at:
      8  *
      9  *  http://www.apache.org/licenses/LICENSE-2.0
     10  *
     11  *  Unless required by applicable law or agreed to in writing, software
     12  *  distributed under the License is distributed on an "AS IS" BASIS,
     13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14  *  See the License for the specific language governing permissions and
     15  *  limitations under the License.
     16  *
     17  ******************************************************************************/
     18 
     19 #define LOG_TAG "bt_vendor"
     20 
     21 #include <assert.h>
     22 #include <dlfcn.h>
     23 #include <utils/Log.h>
     24 
     25 #include "bt_hci_bdroid.h"
     26 #include "bt_vendor_lib.h"
     27 #include "hci.h"
     28 #include "osi.h"
     29 
     30 // TODO: eliminate these three.
     31 extern tHCI_IF *p_hci_if;
     32 extern bool fwcfg_acked;
     33 void lpm_vnd_cback(uint8_t vnd_result);
     34 
     35 static const char *VENDOR_LIBRARY_NAME = "libbt-vendor.so";
     36 static const char *VENDOR_LIBRARY_SYMBOL_NAME = "BLUETOOTH_VENDOR_LIB_INTERFACE";
     37 
     38 static void *lib_handle;
     39 static bt_vendor_interface_t *vendor_interface;
     40 
     41 static void firmware_config_cb(bt_vendor_op_result_t result);
     42 static void sco_config_cb(bt_vendor_op_result_t result);
     43 static void low_power_mode_cb(bt_vendor_op_result_t result);
     44 static void sco_audiostate_cb(bt_vendor_op_result_t result);
     45 static void *buffer_alloc(int size);
     46 static void buffer_free(void *buffer);
     47 static uint8_t transmit_cb(uint16_t opcode, void *buffer, tINT_CMD_CBACK callback);
     48 static void epilog_cb(bt_vendor_op_result_t result);
     49 
     50 static const bt_vendor_callbacks_t vendor_callbacks = {
     51   sizeof(vendor_callbacks),
     52   firmware_config_cb,
     53   sco_config_cb,
     54   low_power_mode_cb,
     55   sco_audiostate_cb,
     56   buffer_alloc,
     57   buffer_free,
     58   transmit_cb,
     59   epilog_cb
     60 };
     61 
     62 bool vendor_open(const uint8_t *local_bdaddr) {
     63   assert(lib_handle == NULL);
     64 
     65   lib_handle = dlopen(VENDOR_LIBRARY_NAME, RTLD_NOW);
     66   if (!lib_handle) {
     67     ALOGE("%s unable to open %s: %s", __func__, VENDOR_LIBRARY_NAME, dlerror());
     68     goto error;
     69   }
     70 
     71   vendor_interface = (bt_vendor_interface_t *)dlsym(lib_handle, VENDOR_LIBRARY_SYMBOL_NAME);
     72   if (!vendor_interface) {
     73     ALOGE("%s unable to find symbol %s in %s: %s", __func__, VENDOR_LIBRARY_SYMBOL_NAME, VENDOR_LIBRARY_NAME, dlerror());
     74     goto error;
     75   }
     76 
     77   int status = vendor_interface->init(&vendor_callbacks, (unsigned char *)local_bdaddr);
     78   if (status) {
     79     ALOGE("%s unable to initialize vendor library: %d", __func__, status);
     80     goto error;
     81   }
     82 
     83   return true;
     84 
     85 error:;
     86   vendor_interface = NULL;
     87   if (lib_handle)
     88     dlclose(lib_handle);
     89   lib_handle = NULL;
     90   return false;
     91 }
     92 
     93 void vendor_close(void) {
     94   if (vendor_interface)
     95     vendor_interface->cleanup();
     96 
     97   if (lib_handle)
     98     dlclose(lib_handle);
     99 
    100   vendor_interface = NULL;
    101   lib_handle = NULL;
    102 }
    103 
    104 int vendor_send_command(bt_vendor_opcode_t opcode, void *param) {
    105   assert(vendor_interface != NULL);
    106 
    107   return vendor_interface->op(opcode, param);
    108 }
    109 
    110 // Called back from vendor library when the firmware configuration
    111 // completes.
    112 static void firmware_config_cb(bt_vendor_op_result_t result) {
    113   assert(bt_hc_cbacks != NULL);
    114 
    115   fwcfg_acked = true;
    116 
    117   bt_hc_postload_result_t status = (result == BT_VND_OP_RESULT_SUCCESS)
    118       ? BT_HC_PRELOAD_SUCCESS
    119       : BT_HC_PRELOAD_FAIL;
    120   bt_hc_cbacks->preload_cb(NULL, status);
    121 }
    122 
    123 // Called back from vendor library to indicate status of previous
    124 // SCO configuration request. This should only happen during the
    125 // postload process.
    126 static void sco_config_cb(UNUSED_ATTR bt_vendor_op_result_t result) {
    127   assert(p_hci_if != NULL);
    128 
    129   // Continue the rest of the postload process.
    130   p_hci_if->get_acl_max_len();
    131 }
    132 
    133 // Called back from vendor library to indicate status of previous
    134 // LPM enable/disable request.
    135 static void low_power_mode_cb(bt_vendor_op_result_t result) {
    136   lpm_vnd_cback(result != BT_VND_OP_RESULT_SUCCESS);
    137 }
    138 
    139 /******************************************************************************
    140 **
    141 ** Function         sco_audiostate_cb
    142 **
    143 ** Description      HOST/CONTROLLER VENDOR LIB CALLBACK API - This function is
    144 **                  called when the libbt-vendor completed vendor specific codec
    145 **                  setup request
    146 **
    147 ** Returns          None
    148 **
    149 ******************************************************************************/
    150 static void sco_audiostate_cb(bt_vendor_op_result_t result)
    151 {
    152     uint8_t status = (result == BT_VND_OP_RESULT_SUCCESS) ? 0 : 1;
    153 
    154     ALOGI("sco_audiostate_cb(status: %d)",status);
    155 }
    156 
    157 // Called by vendor library when it needs an HCI buffer.
    158 static void *buffer_alloc(int size) {
    159   assert(bt_hc_cbacks != NULL);
    160   return bt_hc_cbacks->alloc(size);
    161 }
    162 
    163 // Called by vendor library when it needs to free a buffer allocated with
    164 // |buffer_alloc|.
    165 static void buffer_free(void *buffer) {
    166   assert(bt_hc_cbacks != NULL);
    167   bt_hc_cbacks->dealloc(buffer);
    168 }
    169 
    170 // Called back from vendor library when it wants to send an HCI command.
    171 static uint8_t transmit_cb(uint16_t opcode, void *buffer, tINT_CMD_CBACK callback) {
    172   assert(p_hci_if != NULL);
    173   return p_hci_if->send_int_cmd(opcode, (HC_BT_HDR *)buffer, callback);
    174 }
    175 
    176 // Called back from vendor library when the epilog procedure has
    177 // completed. It is safe to call vendor_interface->cleanup() after
    178 // this callback has been received.
    179 static void epilog_cb(UNUSED_ATTR bt_vendor_op_result_t result) {
    180 }
    181