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