• 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 /******************************************************************************
64 **  Static variables
65 ******************************************************************************/
66 bt_hw_cfg_cb_t hw_cfg_cb;
67 
getmacaddr(unsigned char * addr)68 int getmacaddr(unsigned char *addr)
69 {
70     int i = 0;
71     char data[256], *str;
72     int addr_fd;
73     uint8_t *p_vnd_local_bd_addr = get_vnd_local_bd_addr();
74 
75     char property[100] = {0};
76     (void)memset_s(property, sizeof(property), 0, sizeof(property));
77     (void)strcpy_s(property, sizeof(property), "none");
78     if (strncmp(property, "none", 4L) == 0) {
79         if (strcmp(property, "none") == 0) {
80             return -1;
81         } else if (strcmp(property, "default") == 0) {
82             (void)memcpy_s(addr, BD_ADDR_LEN, p_vnd_local_bd_addr, BD_ADDR_LEN);
83             return 0;
84         } else if ((addr_fd = open(property, O_RDONLY)) != -1) {
85             (void)memset_s(data, sizeof(data), 0, sizeof(data));
86             int ret = read(addr_fd, data, 17L);
87             if (ret < 17L) {
88                 HILOGE("%s, read length = %d", __func__, ret);
89                 close(addr_fd);
90                 return -1;
91             }
92             for (i = 0, str = data; i < 6L; i++) {
93                 addr[5L - i] = (unsigned char)strtoul(str, &str, 16L);
94                 str++;
95             }
96             close(addr_fd);
97             return 0;
98         }
99     }
100     return -1;
101 }
102 
rtk_get_bt_firmware(uint8_t ** fw_buf,char * fw_short_name)103 int rtk_get_bt_firmware(uint8_t **fw_buf, char *fw_short_name)
104 {
105     char filename[PATH_MAX] = {0};
106     struct stat st;
107     int fd = -1;
108     size_t fwsize = 0;
109     size_t buf_size = 0;
110 
111     (void)sprintf_s(filename, sizeof(filename), FIRMWARE_DIRECTORY, fw_short_name);
112     HILOGI("BT fw file: %s", filename);
113 
114     if (stat(filename, &st) < 0) {
115         HILOGE("Can't access firmware, errno:%d", errno);
116         return -1;
117     }
118 
119     fwsize = st.st_size;
120     buf_size = fwsize;
121 
122     if ((fd = open(filename, O_RDONLY)) < 0) {
123         HILOGE("Can't open firmware, errno:%d", errno);
124         return -1;
125     }
126 
127     if (!(*fw_buf = malloc(buf_size))) {
128         HILOGE("Can't alloc memory for fw&config, errno:%d", errno);
129         if (fd >= 0) {
130             close(fd);
131         }
132         return -1;
133     }
134 
135     if (read(fd, *fw_buf, fwsize) < (ssize_t)fwsize) {
136         free(*fw_buf);
137         *fw_buf = NULL;
138         if (fd >= 0) {
139             close(fd);
140         }
141         return -1;
142     }
143 
144     if (fd >= 0) {
145         close(fd);
146     }
147 
148     HILOGI("Load FW OK");
149     return buf_size;
150 }
151 
rtk_get_fw_project_id(uint8_t * p_buf)152 uint8_t rtk_get_fw_project_id(uint8_t *p_buf)
153 {
154     uint8_t opcode;
155     uint8_t len;
156     uint8_t data = 0;
157 
158     do {
159         opcode = *p_buf;
160         len = *(p_buf - 1);
161         if (opcode == 0x00) {
162             if (len == 1) {
163                 data = *(p_buf - 2L);
164                 HILOGI("bt_hw_parse_project_id: opcode %d, len %d, data %d", opcode, len, data);
165                 break;
166             } else {
167                 HILOGW("bt_hw_parse_project_id: invalid len %d", len);
168             }
169         }
170         p_buf -= len + 2L;
171     } while (*p_buf != 0xFF);
172 
173     return data;
174 }
175 
get_heartbeat_from_hardware(void)176 uint8_t get_heartbeat_from_hardware(void)
177 {
178     return hw_cfg_cb.heartbeat;
179 }
180 
rtk_get_patch_entry(bt_hw_cfg_cb_t * cfg_cb)181 struct rtk_epatch_entry *rtk_get_patch_entry(bt_hw_cfg_cb_t *cfg_cb)
182 {
183     uint16_t i;
184     struct rtk_epatch *patch;
185     struct rtk_epatch_entry *entry;
186     uint8_t *p;
187     uint16_t chip_id;
188 
189     patch = (struct rtk_epatch *)cfg_cb->fw_buf;
190     entry = (struct rtk_epatch_entry *)malloc(sizeof(*entry));
191     if (!entry) {
192         HILOGE("rtk_get_patch_entry: failed to allocate mem for patch entry");
193         return NULL;
194     }
195 
196     patch->number_of_patch = le16_to_cpu(patch->number_of_patch);
197 
198     HILOGI("rtk_get_patch_entry: fw_ver 0x%08x, patch_num %d", le32_to_cpu(patch->fw_version), patch->number_of_patch);
199 
200     for (i = 0; i < patch->number_of_patch; i++) {
201         p = cfg_cb->fw_buf + 14L + 2L * i;
202         STREAM_TO_UINT16(chip_id, p);
203         if (chip_id == cfg_cb->eversion + 1) {
204             entry->chip_id = chip_id;
205             p = cfg_cb->fw_buf + 14L + 2L * patch->number_of_patch + 2L * i;
206             STREAM_TO_UINT16(entry->patch_length, p);
207             p = cfg_cb->fw_buf + 14L + 4L * patch->number_of_patch + 4L * i;
208             STREAM_TO_UINT32(entry->patch_offset, p);
209             HILOGI("rtk_get_patch_entry: chip_id %d, patch_len 0x%x, patch_offset 0x%x", entry->chip_id,
210                    entry->patch_length, entry->patch_offset);
211             break;
212         }
213     }
214 
215     if (i == patch->number_of_patch) {
216         HILOGE("rtk_get_patch_entry: failed to get etnry");
217         free(entry);
218         entry = NULL;
219     }
220 
221     return entry;
222 }
223 
224 /******************************************************************************
225 **   LPM Static Functions
226 ******************************************************************************/
227 
228 /*******************************************************************************
229 **
230 ** Function         hw_lpm_ctrl_cback
231 **
232 ** Description      Callback function for lpm enable/disable request
233 **
234 ** Returns          None
235 **
236 *******************************************************************************/
hw_lpm_ctrl_cback(HC_BT_HDR * p_mem)237 void hw_lpm_ctrl_cback(HC_BT_HDR *p_mem)
238 {
239     HC_BT_HDR *p_evt_buf = (HC_BT_HDR *)p_mem;
240 
241     if (*((uint8_t *)(p_evt_buf + 1) + HCI_EVT_CMD_CMPL_STATUS_OFFSET) == 0) {
242     }
243 
244     if (bt_vendor_cbacks) {
245     }
246 }
247 
248 #if (HW_END_WITH_HCI_RESET == TRUE)
249 /******************************************************************************
250  *
251  **
252  ** Function         hw_epilog_cback
253  **
254  ** Description      Callback function for Command Complete Events from HCI
255  **                  commands sent in epilog process.
256  **
257  ** Returns          None
258  **
259  *******************************************************************************/
hw_epilog_cback(HC_BT_HDR * p_mem)260 void hw_epilog_cback(HC_BT_HDR *p_mem)
261 {
262     HC_BT_HDR *p_evt_buf = (HC_BT_HDR *)p_mem;
263     uint8_t *p, status;
264     uint16_t opcode;
265 
266     status = *((uint8_t *)(p_evt_buf + 1) + HCI_EVT_CMD_CMPL_STATUS_OFFSET);
267     p = (uint8_t *)(p_evt_buf + 1) + HCI_EVT_CMD_CMPL_OPCODE_OFFSET;
268     STREAM_TO_UINT16(opcode, p);
269 
270     BTVNDDBG("%s Opcode:0x%04X Status: %d", __FUNCTION__, opcode, status);
271 
272     if (bt_vendor_cbacks) {
273         /* Must free the RX event buffer */
274         bt_vendor_cbacks->dealloc(p_evt_buf);
275 
276         /* Once epilog process is done, must call epilog_cb callback
277            to notify caller */
278         bt_vendor_cbacks->init_cb(BTC_OP_RESULT_SUCCESS);
279     }
280 }
281 
282 /******************************************************************************
283  *
284  **
285  ** Function         hw_epilog_process
286  **
287  ** Description      Sample implementation of epilog process
288  **
289  ** Returns          None
290  **
291  *******************************************************************************/
hw_epilog_process(void)292 void hw_epilog_process(void)
293 {
294     HC_BT_HDR *p_buf = NULL;
295     uint8_t *p;
296 
297     BTVNDDBG("hw_epilog_process");
298 
299     /* Sending a HCI_RESET */
300     if (bt_vendor_cbacks) {
301         /* Must allocate command buffer via HC's alloc API */
302         p_buf = (HC_BT_HDR *)bt_vendor_cbacks->alloc(BT_HC_HDR_SIZE + HCI_CMD_PREAMBLE_SIZE);
303     }
304 
305     if (p_buf) {
306         p_buf->event = MSG_STACK_TO_HC_HCI_CMD;
307         p_buf->offset = 0;
308         p_buf->layer_specific = 0;
309         p_buf->len = HCI_CMD_PREAMBLE_SIZE;
310 
311         p = (uint8_t *)(p_buf + 1);
312         UINT16_TO_STREAM(p, HCI_RESET);
313         *p = 0; /* parameter length */
314 
315         /* Send command via HC's xmit_cb API */
316         bt_vendor_cbacks->xmit_cb(HCI_RESET, p_buf);
317     } else {
318         if (bt_vendor_cbacks) {
319             HILOGE("vendor lib epilog process aborted [no buffer]");
320             bt_vendor_cbacks->init_cb(BTC_OP_RESULT_FAIL);
321         }
322     }
323 }
324 #endif // (HW_END_WITH_HCI_RESET == TRUE)
325