1 /******************************************************************************
2 *
3 * Copyright 2005-2012 Broadcom 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 #include <string.h> // memset
19 #include <cstring>
20
21 #include "bt_target.h" // Must be first to define build configuration
22 #if (BTA_HH_INCLUDED == TRUE)
23
24 #include "bt_trace.h" // Legacy trace logging
25 #include "bta/hh/bta_hh_int.h"
26 #include "btif/include/btif_storage.h"
27 #include "device/include/interop.h"
28 #include "osi/include/osi.h"
29 #include "stack/include/acl_api.h"
30 #include "stack/include/btm_client_interface.h"
31 #include "types/raw_address.h"
32
33 /* if SSR max latency is not defined by remote device, set the default value
34 as half of the link supervision timeout */
35 #define BTA_HH_GET_DEF_SSR_MAX_LAT(x) ((x) >> 1)
36
37 /*****************************************************************************
38 * Constants
39 ****************************************************************************/
40
41 namespace {
42
43 constexpr uint16_t kSsrMaxLatency = 18; /* slots * 0.625ms */
44
45 } // namespace
46
47 /*******************************************************************************
48 *
49 * Function bta_hh_find_cb
50 *
51 * Description Find best available control block according to BD address.
52 *
53 *
54 * Returns void
55 *
56 ******************************************************************************/
bta_hh_find_cb(const RawAddress & bda)57 uint8_t bta_hh_find_cb(const RawAddress& bda) {
58 uint8_t xx;
59
60 /* See how many active devices there are. */
61 for (xx = 0; xx < BTA_HH_MAX_DEVICE; xx++) {
62 /* check if any active/known devices is a match */
63 if ((bda == bta_hh_cb.kdev[xx].addr && !bda.IsEmpty())) {
64 #if (BTA_HH_DEBUG == TRUE)
65 APPL_TRACE_DEBUG("found kdev_cb[%d] hid_handle = %d ", xx,
66 bta_hh_cb.kdev[xx].hid_handle)
67 #endif
68 return xx;
69 }
70 #if (BTA_HH_DEBUG == TRUE)
71 else
72 APPL_TRACE_DEBUG("in_use ? [%d] kdev[%d].hid_handle = %d state = [%d]",
73 bta_hh_cb.kdev[xx].in_use, xx,
74 bta_hh_cb.kdev[xx].hid_handle, bta_hh_cb.kdev[xx].state);
75 #endif
76 }
77
78 /* if no active device match, find a spot for it */
79 for (xx = 0; xx < BTA_HH_MAX_DEVICE; xx++) {
80 if (!bta_hh_cb.kdev[xx].in_use) {
81 bta_hh_cb.kdev[xx].addr = bda;
82 break;
83 }
84 }
85 /* If device list full, report BTA_HH_IDX_INVALID */
86 #if (BTA_HH_DEBUG == TRUE)
87 APPL_TRACE_DEBUG("bta_hh_find_cb:: index = %d while max = %d", xx,
88 BTA_HH_MAX_DEVICE);
89 #endif
90
91 if (xx == BTA_HH_MAX_DEVICE) xx = BTA_HH_IDX_INVALID;
92
93 return xx;
94 }
95
bta_hh_get_cb(const RawAddress & bda)96 tBTA_HH_DEV_CB* bta_hh_get_cb(const RawAddress& bda) {
97 uint8_t idx = bta_hh_find_cb(bda);
98 if (idx == BTA_HH_IDX_INVALID) {
99 return nullptr;
100 }
101 return &bta_hh_cb.kdev[idx];
102 }
103
104 /*******************************************************************************
105 *
106 * Function bta_hh_clean_up_kdev
107 *
108 * Description Clean up device control block when device is removed from
109 * manitainace list, and update control block index map.
110 *
111 * Returns void
112 *
113 ******************************************************************************/
bta_hh_clean_up_kdev(tBTA_HH_DEV_CB * p_cb)114 void bta_hh_clean_up_kdev(tBTA_HH_DEV_CB* p_cb) {
115 uint8_t index;
116
117 if (p_cb->hid_handle != BTA_HH_INVALID_HANDLE) {
118 if (p_cb->is_le_device)
119 bta_hh_cb.le_cb_index[BTA_HH_GET_LE_CB_IDX(p_cb->hid_handle)] =
120 BTA_HH_IDX_INVALID;
121 else
122 bta_hh_cb.cb_index[p_cb->hid_handle] = BTA_HH_IDX_INVALID;
123 }
124
125 /* reset device control block */
126 index = p_cb->index; /* Preserve index for this control block */
127
128 /* Free buffer for report descriptor info */
129 osi_free_and_reset((void**)&p_cb->dscp_info.descriptor.dsc_list);
130
131 memset(p_cb, 0, sizeof(tBTA_HH_DEV_CB)); /* Reset control block */
132
133 p_cb->index = index; /* Restore index for this control block */
134 p_cb->state = BTA_HH_IDLE_ST;
135 p_cb->hid_handle = BTA_HH_INVALID_HANDLE;
136 }
137 /*******************************************************************************
138 *
139 * Function bta_hh_update_di_info
140 *
141 * Description Maintain a known device list for BTA HH.
142 *
143 * Returns void
144 *
145 ******************************************************************************/
bta_hh_update_di_info(tBTA_HH_DEV_CB * p_cb,uint16_t vendor_id,uint16_t product_id,uint16_t version,uint8_t flag)146 void bta_hh_update_di_info(tBTA_HH_DEV_CB* p_cb, uint16_t vendor_id,
147 uint16_t product_id, uint16_t version,
148 uint8_t flag)
149 {
150 #if (BTA_HH_DEBUG == TRUE)
151 APPL_TRACE_DEBUG("vendor_id = 0x%2x product_id = 0x%2x version = 0x%2x",
152 vendor_id, product_id, version);
153 #endif
154 p_cb->dscp_info.vendor_id = vendor_id;
155 p_cb->dscp_info.product_id = product_id;
156 p_cb->dscp_info.version = version;
157 p_cb->dscp_info.flag = flag;
158 }
159 /*******************************************************************************
160 *
161 * Function bta_hh_add_device_to_list
162 *
163 * Description Maintain a known device list for BTA HH.
164 *
165 * Returns void
166 *
167 ******************************************************************************/
bta_hh_add_device_to_list(tBTA_HH_DEV_CB * p_cb,uint8_t handle,uint16_t attr_mask,const tHID_DEV_DSCP_INFO * p_dscp_info,uint8_t sub_class,uint16_t ssr_max_latency,uint16_t ssr_min_tout,uint8_t app_id)168 void bta_hh_add_device_to_list(tBTA_HH_DEV_CB* p_cb, uint8_t handle,
169 uint16_t attr_mask,
170 const tHID_DEV_DSCP_INFO* p_dscp_info,
171 uint8_t sub_class, uint16_t ssr_max_latency,
172 uint16_t ssr_min_tout, uint8_t app_id) {
173 #if (BTA_HH_DEBUG == TRUE)
174 APPL_TRACE_DEBUG("subclass = 0x%2x", sub_class);
175 #endif
176
177 p_cb->hid_handle = handle;
178 p_cb->in_use = true;
179 p_cb->attr_mask = attr_mask;
180
181 p_cb->sub_class = sub_class;
182 p_cb->app_id = app_id;
183
184 p_cb->dscp_info.ssr_max_latency = ssr_max_latency;
185 p_cb->dscp_info.ssr_min_tout = ssr_min_tout;
186
187 /* store report descriptor info */
188 if (p_dscp_info) {
189 osi_free_and_reset((void**)&p_cb->dscp_info.descriptor.dsc_list);
190
191 if (p_dscp_info->dl_len) {
192 p_cb->dscp_info.descriptor.dsc_list =
193 (uint8_t*)osi_malloc(p_dscp_info->dl_len);
194 p_cb->dscp_info.descriptor.dl_len = p_dscp_info->dl_len;
195 memcpy(p_cb->dscp_info.descriptor.dsc_list, p_dscp_info->dsc_list,
196 p_dscp_info->dl_len);
197 }
198 }
199 }
200
201 /*******************************************************************************
202 *
203 * Function bta_hh_tod_spt
204 *
205 * Description Check to see if this type of device is supported
206 *
207 * Returns
208 *
209 ******************************************************************************/
bta_hh_tod_spt(tBTA_HH_DEV_CB * p_cb,uint8_t sub_class)210 bool bta_hh_tod_spt(tBTA_HH_DEV_CB* p_cb, uint8_t sub_class) {
211 uint8_t xx;
212 uint8_t cod = (sub_class >> 2); /* lower two bits are reserved */
213
214 for (xx = 0; xx < p_bta_hh_cfg->max_devt_spt; xx++) {
215 if (cod == (uint8_t)p_bta_hh_cfg->p_devt_list[xx].tod) {
216 p_cb->app_id = p_bta_hh_cfg->p_devt_list[xx].app_id;
217 #if (BTA_HH_DEBUG == TRUE)
218 APPL_TRACE_EVENT("bta_hh_tod_spt sub_class:0x%x supported", sub_class);
219 #endif
220 return true;
221 }
222 }
223 #if (BTA_HH_DEBUG == TRUE)
224 APPL_TRACE_EVENT("bta_hh_tod_spt sub_class:0x%x NOT supported", sub_class);
225 #endif
226 return false;
227 }
228
229
230 /*******************************************************************************
231 *
232 * Function bta_hh_read_ssr_param
233 *
234 * Description Read the SSR Parameter for the remote device
235 *
236 * Returns tBTA_HH_STATUS operation status
237 *
238 ******************************************************************************/
bta_hh_read_ssr_param(const RawAddress & bd_addr,uint16_t * p_max_ssr_lat,uint16_t * p_min_ssr_tout)239 tBTA_HH_STATUS bta_hh_read_ssr_param(const RawAddress& bd_addr,
240 uint16_t* p_max_ssr_lat,
241 uint16_t* p_min_ssr_tout) {
242 tBTA_HH_DEV_CB* p_cb = bta_hh_get_cb(bd_addr);
243 if (p_cb == nullptr) {
244 LOG_WARN("Unable to find device:%s", PRIVATE_ADDRESS(bd_addr));
245 return BTA_HH_ERR;
246 }
247
248 /* if remote device does not have HIDSSRHostMaxLatency attribute in SDP,
249 set SSR max latency default value here. */
250 if (p_cb->dscp_info.ssr_max_latency == HID_SSR_PARAM_INVALID) {
251 /* The default is calculated as half of link supervision timeout.*/
252
253 uint16_t ssr_max_latency;
254 if (get_btm_client_interface().link_controller.BTM_GetLinkSuperTout(
255 p_cb->addr, &ssr_max_latency) != BTM_SUCCESS) {
256 LOG_WARN("Unable to get supervision timeout for peer:%s",
257 PRIVATE_ADDRESS(p_cb->addr));
258 return BTA_HH_ERR;
259 }
260 ssr_max_latency = BTA_HH_GET_DEF_SSR_MAX_LAT(ssr_max_latency);
261
262 /* per 1.1 spec, if the newly calculated max latency is greater than
263 BTA_HH_SSR_MAX_LATENCY_DEF which is 500ms, use
264 BTA_HH_SSR_MAX_LATENCY_DEF */
265 if (ssr_max_latency > BTA_HH_SSR_MAX_LATENCY_DEF)
266 ssr_max_latency = BTA_HH_SSR_MAX_LATENCY_DEF;
267
268 char remote_name[BTM_MAX_REM_BD_NAME_LEN] = "";
269 if (btif_storage_get_stored_remote_name(bd_addr, remote_name)) {
270 if (interop_match_name(INTEROP_HID_HOST_LIMIT_SNIFF_INTERVAL,
271 remote_name)) {
272 if (ssr_max_latency > kSsrMaxLatency /* slots * 0.625ms */) {
273 ssr_max_latency = kSsrMaxLatency;
274 }
275 }
276 }
277
278 *p_max_ssr_lat = ssr_max_latency;
279 } else
280 *p_max_ssr_lat = p_cb->dscp_info.ssr_max_latency;
281
282 if (p_cb->dscp_info.ssr_min_tout == HID_SSR_PARAM_INVALID)
283 *p_min_ssr_tout = BTA_HH_SSR_MIN_TOUT_DEF;
284 else
285 *p_min_ssr_tout = p_cb->dscp_info.ssr_min_tout;
286
287 return BTA_HH_OK;
288 }
289
290 /*******************************************************************************
291 *
292 * Function bta_hh_cleanup_disable
293 *
294 * Description when disable finished, cleanup control block and send
295 * callback
296 *
297 *
298 * Returns void
299 *
300 ******************************************************************************/
bta_hh_cleanup_disable(tBTA_HH_STATUS status)301 void bta_hh_cleanup_disable(tBTA_HH_STATUS status) {
302 uint8_t xx;
303 /* free buffer in CB holding report descriptors */
304 for (xx = 0; xx < BTA_HH_MAX_DEVICE; xx++) {
305 osi_free_and_reset(
306 (void**)&bta_hh_cb.kdev[xx].dscp_info.descriptor.dsc_list);
307 }
308
309 if (bta_hh_cb.p_disc_db) {
310 /* Cancel SDP if it had been started. */
311 (void)SDP_CancelServiceSearch (bta_hh_cb.p_disc_db);
312 osi_free_and_reset((void**)&bta_hh_cb.p_disc_db);
313 }
314
315 if (bta_hh_cb.p_cback) {
316 tBTA_HH bta_hh;
317 bta_hh.status = status;
318 (*bta_hh_cb.p_cback)(BTA_HH_DISABLE_EVT, &bta_hh);
319 /* all connections are down, no waiting for diconnect */
320 memset(&bta_hh_cb, 0, sizeof(tBTA_HH_CB));
321 }
322 }
323
324 /*******************************************************************************
325 *
326 * Function bta_hh_dev_handle_to_cb_idx
327 *
328 * Description convert a HID device handle to the device control block
329 * index.
330 *
331 *
332 * Returns uint8_t: index of the device control block.
333 *
334 ******************************************************************************/
bta_hh_dev_handle_to_cb_idx(uint8_t dev_handle)335 uint8_t bta_hh_dev_handle_to_cb_idx(uint8_t dev_handle) {
336 uint8_t index = BTA_HH_IDX_INVALID;
337
338 if (BTA_HH_IS_LE_DEV_HDL(dev_handle)) {
339 if (BTA_HH_IS_LE_DEV_HDL_VALID(dev_handle))
340 index = bta_hh_cb.le_cb_index[BTA_HH_GET_LE_CB_IDX(dev_handle)];
341 #if (BTA_HH_DEBUG == TRUE)
342 APPL_TRACE_DEBUG("bta_hh_dev_handle_to_cb_idx dev_handle = %d index = %d",
343 dev_handle, index);
344 #endif
345 } else
346 /* regular HID device checking */
347 if (dev_handle < BTA_HH_MAX_KNOWN)
348 index = bta_hh_cb.cb_index[dev_handle];
349
350 return index;
351 }
352 #if (BTA_HH_DEBUG == TRUE)
353 /*******************************************************************************
354 *
355 * Function bta_hh_trace_dev_db
356 *
357 * Description Check to see if this type of device is supported
358 *
359 * Returns
360 *
361 ******************************************************************************/
bta_hh_trace_dev_db(void)362 void bta_hh_trace_dev_db(void) {
363 uint8_t xx;
364
365 APPL_TRACE_DEBUG("bta_hh_trace_dev_db:: Device DB list********************");
366
367 for (xx = 0; xx < BTA_HH_MAX_DEVICE; xx++) {
368 APPL_TRACE_DEBUG("kdev[%d] in_use[%d] handle[%d] ", xx,
369 bta_hh_cb.kdev[xx].in_use, bta_hh_cb.kdev[xx].hid_handle);
370
371 APPL_TRACE_DEBUG(
372 "\t\t\t attr_mask[%04x] state [%d] sub_class[%02x] index = %d",
373 bta_hh_cb.kdev[xx].attr_mask, bta_hh_cb.kdev[xx].state,
374 bta_hh_cb.kdev[xx].sub_class, bta_hh_cb.kdev[xx].index);
375 }
376 APPL_TRACE_DEBUG("*********************************************************");
377 }
378 #endif
379 #endif /* HL_INCLUDED */
380