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 
vendor_open(const uint8_t * local_bdaddr,const hci_t * hci_interface)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 
vendor_close(void)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 
send_command(vendor_opcode_t opcode,void * param)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 
send_async_command(vendor_async_opcode_t opcode,void * param)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 
set_callback(vendor_async_opcode_t opcode,vendor_cb callback)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.
firmware_config_cb(bt_vendor_op_result_t result)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.
sco_config_cb(bt_vendor_op_result_t result)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.
low_power_mode_cb(bt_vendor_op_result_t result)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 ******************************************************************************/
sco_audiostate_cb(bt_vendor_op_result_t result)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.
buffer_alloc_cb(int size)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|.
buffer_free_cb(void * buffer)163 static void buffer_free_cb(void *buffer) {
164   buffer_allocator->free(buffer);
165 }
166 
transmit_completed_callback(BT_HDR * response,void * context)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.
transmit_cb(UNUSED_ATTR uint16_t opcode,void * buffer,tINT_CMD_CBACK callback)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.
epilog_cb(bt_vendor_op_result_t result)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.
a2dp_offload_cb(bt_vendor_op_result_t result,bt_vendor_opcode_t op,uint8_t bta_av_handle)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 
vendor_get_interface()225 const vendor_t *vendor_get_interface() {
226   buffer_allocator = buffer_allocator_get_interface();
227   return &interface;
228 }
229