1 /******************************************************************************
2 *
3 * Copyright (C) 2009-2018 Realtek Corporation
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 /******************************************************************************
20 *
21 * Filename: hardware.c
22 *
23 * Description: Contains controller-specific functions, like
24 * firmware patch download
25 * low power mode operations
26 *
27 ******************************************************************************/
28
29 #define LOG_TAG "bt_hwcfg"
30 #define RTKBT_RELEASE_NAME "20190717_BT_ANDROID_9.0"
31
32 #include "hardware.h"
33
34 #include <byteswap.h>
35 #include <ctype.h>
36 #include <dirent.h>
37 #include <endian.h>
38 #include <errno.h>
39 #include <fcntl.h>
40 #include <signal.h>
41 #include <stdlib.h>
42 #include <sys/stat.h>
43 #include <sys/types.h>
44 #include <time.h>
45 #include <unistd.h>
46 #include <utils/Log.h>
47
48 #include "bt_hci_bdroid.h"
49 #include "bt_vendor_lib.h"
50 #include "bt_vendor_rtk.h"
51 #include "upio.h"
52 #include "userial.h"
53 #include "userial_vendor.h"
54
55 /******************************************************************************
56 ** Constants & Macros
57 ******************************************************************************/
58
59 /******************************************************************************
60 ** Externs
61 ******************************************************************************/
62
63 // void hw_config_cback(void *p_evt_buf);
64 // void hw_usb_config_cback(void *p_evt_buf);
65
66 extern uint8_t vnd_local_bd_addr[BD_ADDR_LEN];
67 extern bool rtkbt_auto_restart;
68
69 /******************************************************************************
70 ** Static variables
71 ******************************************************************************/
72 bt_hw_cfg_cb_t hw_cfg_cb;
73
74 /*
75 static bt_lpm_param_t lpm_param =
76 {
77 LPM_SLEEP_MODE,
78 LPM_IDLE_THRESHOLD,
79 LPM_HC_IDLE_THRESHOLD,
80 LPM_BT_WAKE_POLARITY,
81 LPM_HOST_WAKE_POLARITY,
82 LPM_ALLOW_HOST_SLEEP_DURING_SCO,
83 LPM_COMBINE_SLEEP_MODE_AND_LPM,
84 LPM_ENABLE_UART_TXD_TRI_STATE,*/
85 // 0, /* not applicable */
86 // 0, /* not applicable */
87 // 0, /* not applicable */
88 /*LPM_PULSED_HOST_WAKE
89 };*/
90
getmacaddr(unsigned char * addr)91 int getmacaddr(unsigned char *addr)
92 {
93 int i = 0;
94 char data[256], *str;
95 int addr_fd;
96
97 char property[100] = {0};
98 memset(property, 0, sizeof(property));
99 strcpy(property, "none");
100 if (strncmp(property, "none", 4) == 0)
101 {
102 if (strcmp(property, "none") == 0)
103 {
104 return -1;
105 }
106 else if (strcmp(property, "default") == 0)
107 {
108 memcpy(addr, vnd_local_bd_addr, BD_ADDR_LEN);
109 return 0;
110 }
111 else if ((addr_fd = open(property, O_RDONLY)) != -1)
112 {
113 memset(data, 0, sizeof(data));
114 int ret = read(addr_fd, data, 17);
115 if (ret < 17)
116 {
117 HILOGE("%s, read length = %d", __func__, ret);
118 close(addr_fd);
119 return -1;
120 }
121 for (i = 0, str = data; i < 6; i++)
122 {
123 addr[5 - i] = (unsigned char)strtoul(str, &str, 16);
124 str++;
125 }
126 close(addr_fd);
127 return 0;
128 }
129 }
130 return -1;
131 }
132
rtk_get_bt_firmware(uint8_t ** fw_buf,char * fw_short_name)133 int rtk_get_bt_firmware(uint8_t **fw_buf, char *fw_short_name)
134 {
135 char filename[PATH_MAX] = {0};
136 struct stat st;
137 int fd = -1;
138 size_t fwsize = 0;
139 size_t buf_size = 0;
140
141 sprintf(filename, FIRMWARE_DIRECTORY, fw_short_name);
142 HILOGI("BT fw file: %s", filename);
143
144 if (stat(filename, &st) < 0)
145 {
146 HILOGE("Can't access firmware, errno:%d", errno);
147 return -1;
148 }
149
150 fwsize = st.st_size;
151 buf_size = fwsize;
152
153 if ((fd = open(filename, O_RDONLY)) < 0)
154 {
155 HILOGE("Can't open firmware, errno:%d", errno);
156 return -1;
157 }
158
159 if (!(*fw_buf = malloc(buf_size)))
160 {
161 HILOGE("Can't alloc memory for fw&config, errno:%d", errno);
162 if (fd >= 0)
163 close(fd);
164 return -1;
165 }
166
167 if (read(fd, *fw_buf, fwsize) < (ssize_t)fwsize)
168 {
169 free(*fw_buf);
170 *fw_buf = NULL;
171 if (fd >= 0)
172 close(fd);
173 return -1;
174 }
175
176 if (fd >= 0)
177 close(fd);
178
179 HILOGI("Load FW OK");
180 return buf_size;
181 }
182
rtk_get_fw_project_id(uint8_t * p_buf)183 uint8_t rtk_get_fw_project_id(uint8_t *p_buf)
184 {
185 uint8_t opcode;
186 uint8_t len;
187 uint8_t data = 0;
188
189 do
190 {
191 opcode = *p_buf;
192 len = *(p_buf - 1);
193 if (opcode == 0x00)
194 {
195 if (len == 1)
196 {
197 data = *(p_buf - 2);
198 HILOGI("bt_hw_parse_project_id: opcode %d, len %d, data %d", opcode,
199 len, data);
200 break;
201 }
202 else
203 {
204 HILOGW("bt_hw_parse_project_id: invalid len %d", len);
205 }
206 }
207 p_buf -= len + 2;
208 } while (*p_buf != 0xFF);
209
210 return data;
211 }
212
get_heartbeat_from_hardware()213 uint8_t get_heartbeat_from_hardware() { return hw_cfg_cb.heartbeat; }
214
rtk_get_patch_entry(bt_hw_cfg_cb_t * cfg_cb)215 struct rtk_epatch_entry *rtk_get_patch_entry(bt_hw_cfg_cb_t *cfg_cb)
216 {
217 uint16_t i;
218 struct rtk_epatch *patch;
219 struct rtk_epatch_entry *entry;
220 uint8_t *p;
221 uint16_t chip_id;
222
223 patch = (struct rtk_epatch *)cfg_cb->fw_buf;
224 entry = (struct rtk_epatch_entry *)malloc(sizeof(*entry));
225 if (!entry)
226 {
227 HILOGE("rtk_get_patch_entry: failed to allocate mem for patch entry");
228 return NULL;
229 }
230
231 patch->number_of_patch = le16_to_cpu(patch->number_of_patch);
232
233 HILOGI("rtk_get_patch_entry: fw_ver 0x%08x, patch_num %d",
234 le32_to_cpu(patch->fw_version), patch->number_of_patch);
235
236 for (i = 0; i < patch->number_of_patch; i++)
237 {
238 p = cfg_cb->fw_buf + 14 + 2 * i;
239 STREAM_TO_UINT16(chip_id, p);
240 if (chip_id == cfg_cb->eversion + 1)
241 {
242 entry->chip_id = chip_id;
243 p = cfg_cb->fw_buf + 14 + 2 * patch->number_of_patch + 2 * i;
244 STREAM_TO_UINT16(entry->patch_length, p);
245 p = cfg_cb->fw_buf + 14 + 4 * patch->number_of_patch + 4 * i;
246 STREAM_TO_UINT32(entry->patch_offset, p);
247 HILOGI(
248 "rtk_get_patch_entry: chip_id %d, patch_len 0x%x, patch_offset 0x%x",
249 entry->chip_id, entry->patch_length, entry->patch_offset);
250 break;
251 }
252 }
253
254 if (i == patch->number_of_patch)
255 {
256 HILOGE("rtk_get_patch_entry: failed to get etnry");
257 free(entry);
258 entry = NULL;
259 }
260
261 return entry;
262 }
263
264 /******************************************************************************
265 ** LPM Static Functions
266 ******************************************************************************/
267
268 /*******************************************************************************
269 **
270 ** Function hw_lpm_ctrl_cback
271 **
272 ** Description Callback function for lpm enable/disable request
273 **
274 ** Returns None
275 **
276 *******************************************************************************/
hw_lpm_ctrl_cback(void * p_mem)277 void hw_lpm_ctrl_cback(void *p_mem)
278 {
279 HC_BT_HDR *p_evt_buf = (HC_BT_HDR *)p_mem;
280 // bt_vendor_op_result_t status = BTC_OP_RESULT_FAIL;
281
282 if (*((uint8_t *)(p_evt_buf + 1) + HCI_EVT_CMD_CMPL_STATUS_OFFSET) == 0)
283 {
284 // status = BTC_OP_RESULT_SUCCESS;
285 }
286
287 if (bt_vendor_cbacks)
288 {
289 // bt_vendor_cbacks->lpm_cb(status);
290 bt_vendor_cbacks->dealloc(p_evt_buf);
291 }
292 }
293
294 #if (HW_END_WITH_HCI_RESET == TRUE)
295 /******************************************************************************
296 *
297 **
298 ** Function hw_epilog_cback
299 **
300 ** Description Callback function for Command Complete Events from HCI
301 ** commands sent in epilog process.
302 **
303 ** Returns None
304 **
305 *******************************************************************************/
hw_epilog_cback(void * p_mem)306 void hw_epilog_cback(void *p_mem)
307 {
308 HC_BT_HDR *p_evt_buf = (HC_BT_HDR *)p_mem;
309 uint8_t *p, status;
310 uint16_t opcode;
311
312 status = *((uint8_t *)(p_evt_buf + 1) + HCI_EVT_CMD_CMPL_STATUS_OFFSET);
313 p = (uint8_t *)(p_evt_buf + 1) + HCI_EVT_CMD_CMPL_OPCODE_OFFSET;
314 STREAM_TO_UINT16(opcode, p);
315
316 BTVNDDBG("%s Opcode:0x%04X Status: %d", __FUNCTION__, opcode, status);
317
318 if (bt_vendor_cbacks)
319 {
320 /* Must free the RX event buffer */
321 bt_vendor_cbacks->dealloc(p_evt_buf);
322
323 /* Once epilog process is done, must call epilog_cb callback
324 to notify caller */
325 bt_vendor_cbacks->init_cb(BTC_OP_RESULT_SUCCESS);
326 }
327 }
328
329 /******************************************************************************
330 *
331 **
332 ** Function hw_epilog_process
333 **
334 ** Description Sample implementation of epilog process
335 **
336 ** Returns None
337 **
338 *******************************************************************************/
hw_epilog_process(void)339 void hw_epilog_process(void)
340 {
341 HC_BT_HDR *p_buf = NULL;
342 uint8_t *p;
343
344 BTVNDDBG("hw_epilog_process");
345
346 /* Sending a HCI_RESET */
347 if (bt_vendor_cbacks)
348 {
349 /* Must allocate command buffer via HC's alloc API */
350 p_buf = (HC_BT_HDR *)bt_vendor_cbacks->alloc(BT_HC_HDR_SIZE +
351 HCI_CMD_PREAMBLE_SIZE);
352 }
353
354 if (p_buf)
355 {
356 p_buf->event = MSG_STACK_TO_HC_HCI_CMD;
357 p_buf->offset = 0;
358 p_buf->layer_specific = 0;
359 p_buf->len = HCI_CMD_PREAMBLE_SIZE;
360
361 p = (uint8_t *)(p_buf + 1);
362 UINT16_TO_STREAM(p, HCI_RESET);
363 *p = 0; /* parameter length */
364
365 /* Send command via HC's xmit_cb API */
366 bt_vendor_cbacks->xmit_cb(HCI_RESET, p_buf);
367 }
368 else
369 {
370 if (bt_vendor_cbacks)
371 {
372 HILOGE("vendor lib epilog process aborted [no buffer]");
373 bt_vendor_cbacks->init_cb(BTC_OP_RESULT_FAIL);
374 }
375 }
376 }
377 #endif // (HW_END_WITH_HCI_RESET == TRUE)
378