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