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