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 "vendor.h"
     22 
     23 #include <assert.h>
     24 #include <dlfcn.h>
     25 
     26 #include "buffer_allocator.h"
     27 #include "bt_vendor_lib.h"
     28 #include "bta_av_api.h"
     29 #include "osi/include/log.h"
     30 #include "osi/include/osi.h"
     31 
     32 
     33 static const char *VENDOR_LIBRARY_NAME = "libbt-vendor.so";
     34 static const char *VENDOR_LIBRARY_SYMBOL_NAME = "BLUETOOTH_VENDOR_LIB_INTERFACE";
     35 
     36 static const vendor_t interface;
     37 static const allocator_t *buffer_allocator;
     38 static const hci_t *hci;
     39 static vendor_cb callbacks[VENDOR_LAST_OP];
     40 
     41 static void *lib_handle;
     42 static bt_vendor_interface_t *lib_interface;
     43 static const bt_vendor_callbacks_t lib_callbacks;
     44 
     45 // Interface functions
     46 
     47 static bool vendor_open(
     48     const uint8_t *local_bdaddr,
     49     const hci_t *hci_interface) {
     50   assert(lib_handle == NULL);
     51   hci = hci_interface;
     52 
     53   lib_handle = dlopen(VENDOR_LIBRARY_NAME, RTLD_NOW);
     54   if (!lib_handle) {
     55     LOG_ERROR(LOG_TAG, "%s unable to open %s: %s", __func__, VENDOR_LIBRARY_NAME, dlerror());
     56     goto error;
     57   }
     58 
     59   lib_interface = (bt_vendor_interface_t *)dlsym(lib_handle, VENDOR_LIBRARY_SYMBOL_NAME);
     60   if (!lib_interface) {
     61     LOG_ERROR(LOG_TAG, "%s unable to find symbol %s in %s: %s", __func__, VENDOR_LIBRARY_SYMBOL_NAME, VENDOR_LIBRARY_NAME, dlerror());
     62     goto error;
     63   }
     64 
     65   LOG_INFO(LOG_TAG, "alloc value %p", lib_callbacks.alloc);
     66 
     67   int status = lib_interface->init(&lib_callbacks, (unsigned char *)local_bdaddr);
     68   if (status) {
     69     LOG_ERROR(LOG_TAG, "%s unable to initialize vendor library: %d", __func__, status);
     70     goto error;
     71   }
     72 
     73   return true;
     74 
     75 error:;
     76   lib_interface = NULL;
     77   if (lib_handle)
     78     dlclose(lib_handle);
     79   lib_handle = NULL;
     80   return false;
     81 }
     82 
     83 static void vendor_close(void) {
     84   if (lib_interface)
     85     lib_interface->cleanup();
     86 
     87   if (lib_handle)
     88     dlclose(lib_handle);
     89 
     90   lib_interface = NULL;
     91   lib_handle = NULL;
     92 }
     93 
     94 static int send_command(vendor_opcode_t opcode, void *param) {
     95   assert(lib_interface != NULL);
     96   return lib_interface->op((bt_vendor_opcode_t)opcode, param);
     97 }
     98 
     99 static int send_async_command(vendor_async_opcode_t opcode, void *param) {
    100   assert(lib_interface != NULL);
    101   return lib_interface->op((bt_vendor_opcode_t)opcode, param);
    102 }
    103 
    104 static void set_callback(vendor_async_opcode_t opcode, vendor_cb callback) {
    105   callbacks[opcode] = callback;
    106 }
    107 
    108 // Internal functions
    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   LOG_INFO(LOG_TAG, "firmware callback");
    114   vendor_cb callback = callbacks[VENDOR_CONFIGURE_FIRMWARE];
    115   assert(callback != NULL);
    116   callback(result == BT_VND_OP_RESULT_SUCCESS);
    117 }
    118 
    119 // Called back from vendor library to indicate status of previous
    120 // SCO configuration request. This should only happen during the
    121 // postload process.
    122 static void sco_config_cb(bt_vendor_op_result_t result) {
    123   LOG_INFO(LOG_TAG, "%s", __func__);
    124   vendor_cb callback = callbacks[VENDOR_CONFIGURE_SCO];
    125   assert(callback != NULL);
    126   callback(result == BT_VND_OP_RESULT_SUCCESS);
    127 }
    128 
    129 // Called back from vendor library to indicate status of previous
    130 // LPM enable/disable request.
    131 static void low_power_mode_cb(bt_vendor_op_result_t result) {
    132   LOG_INFO(LOG_TAG, "%s", __func__);
    133   vendor_cb callback = callbacks[VENDOR_SET_LPM_MODE];
    134   assert(callback != NULL);
    135   callback(result == BT_VND_OP_RESULT_SUCCESS);
    136 }
    137 
    138 /******************************************************************************
    139 **
    140 ** Function         sco_audiostate_cb
    141 **
    142 ** Description      HOST/CONTROLLER VENDOR LIB CALLBACK API - This function is
    143 **                  called when the libbt-vendor completed vendor specific codec
    144 **                  setup request
    145 **
    146 ** Returns          None
    147 **
    148 ******************************************************************************/
    149 static void sco_audiostate_cb(bt_vendor_op_result_t result)
    150 {
    151     uint8_t status = (result == BT_VND_OP_RESULT_SUCCESS) ? 0 : 1;
    152 
    153     LOG_INFO(LOG_TAG, "sco_audiostate_cb(status: %d)",status);
    154 }
    155 
    156 // Called by vendor library when it needs an HCI buffer.
    157 static void *buffer_alloc_cb(int size) {
    158   return buffer_allocator->alloc(size);
    159 }
    160 
    161 // Called by vendor library when it needs to free a buffer allocated with
    162 // |buffer_alloc_cb|.
    163 static void buffer_free_cb(void *buffer) {
    164   buffer_allocator->free(buffer);
    165 }
    166 
    167 static void transmit_completed_callback(BT_HDR *response, void *context) {
    168   // Call back to the vendor library if it provided a callback to call.
    169   if (context) {
    170     ((tINT_CMD_CBACK)context)(response);
    171   } else {
    172     // HCI layer expects us to release the response.
    173     buffer_free_cb(response);
    174   }
    175 }
    176 
    177 // Called back from vendor library when it wants to send an HCI command.
    178 static uint8_t transmit_cb(UNUSED_ATTR uint16_t opcode, void *buffer, tINT_CMD_CBACK callback) {
    179   assert(hci != NULL);
    180   hci->transmit_command((BT_HDR *)buffer, transmit_completed_callback, NULL, callback);
    181   return true;
    182 }
    183 
    184 // Called back from vendor library when the epilog procedure has
    185 // completed. It is safe to call vendor_interface->cleanup() after
    186 // this callback has been received.
    187 static void epilog_cb(bt_vendor_op_result_t result) {
    188   LOG_INFO(LOG_TAG, "%s", __func__);
    189   vendor_cb callback = callbacks[VENDOR_DO_EPILOG];
    190   assert(callback != NULL);
    191   callback(result == BT_VND_OP_RESULT_SUCCESS);
    192 }
    193 
    194 // Called back from vendor library when the a2dp offload machine has to report status of
    195 // an a2dp offload command.
    196 static void a2dp_offload_cb(bt_vendor_op_result_t result, bt_vendor_opcode_t op, uint8_t bta_av_handle) {
    197   tBTA_AV_STATUS status = (result == BT_VND_OP_RESULT_SUCCESS) ? BTA_AV_SUCCESS : BTA_AV_FAIL_RESOURCES;
    198 
    199   if (op == BT_VND_OP_A2DP_OFFLOAD_START) {
    200       BTA_AvOffloadStartRsp(bta_av_handle, status);
    201   }
    202 }
    203 
    204 static const bt_vendor_callbacks_t lib_callbacks = {
    205   sizeof(lib_callbacks),
    206   firmware_config_cb,
    207   sco_config_cb,
    208   low_power_mode_cb,
    209   sco_audiostate_cb,
    210   buffer_alloc_cb,
    211   buffer_free_cb,
    212   transmit_cb,
    213   epilog_cb,
    214   a2dp_offload_cb
    215 };
    216 
    217 static const vendor_t interface = {
    218   vendor_open,
    219   vendor_close,
    220   send_command,
    221   send_async_command,
    222   set_callback,
    223 };
    224 
    225 const vendor_t *vendor_get_interface() {
    226   buffer_allocator = buffer_allocator_get_interface();
    227   return &interface;
    228 }
    229