• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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