1 /****************************************************************************** 2 * 3 * Copyright (C) 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> 19 20 #include "bt_target.h" 21 #if defined(BTA_HH_INCLUDED) && (BTA_HH_INCLUDED == TRUE) 22 23 24 #include "bta_hh_int.h" 25 26 /* if SSR max latency is not defined by remote device, set the default value 27 as half of the link supervision timeout */ 28 #define BTA_HH_GET_DEF_SSR_MAX_LAT(x) ((x)>> 1) 29 30 /***************************************************************************** 31 ** Constants 32 *****************************************************************************/ 33 #define BTA_HH_KB_CTRL_MASK 0x11 34 #define BTA_HH_KB_SHIFT_MASK 0x22 35 #define BTA_HH_KB_ALT_MASK 0x44 36 #define BTA_HH_KB_GUI_MASK 0x88 37 38 #define BTA_HH_KB_CAPS_LOCK 0x39 /* caps lock */ 39 #define BTA_HH_KB_NUM_LOCK 0x53 /* num lock */ 40 41 42 #define BTA_HH_MAX_RPT_CHARS 8 43 44 static const UINT8 bta_hh_mod_key_mask[BTA_HH_MOD_MAX_KEY] = 45 { 46 BTA_HH_KB_CTRL_MASK, 47 BTA_HH_KB_SHIFT_MASK, 48 BTA_HH_KB_ALT_MASK, 49 BTA_HH_KB_GUI_MASK 50 }; 51 52 53 /******************************************************************************* 54 ** 55 ** Function bta_hh_find_cb 56 ** 57 ** Description Find best available control block according to BD address. 58 ** 59 ** 60 ** Returns void 61 ** 62 *******************************************************************************/ 63 UINT8 bta_hh_find_cb(BD_ADDR bda) 64 { 65 UINT8 xx; 66 67 /* See how many active devices there are. */ 68 for (xx = 0; xx < BTA_HH_MAX_DEVICE; xx++) 69 { 70 /* check if any active/known devices is a match */ 71 if ((!bdcmp (bda, bta_hh_cb.kdev[xx].addr) && 72 bdcmp(bda, bd_addr_null) != 0) ) 73 { 74 #if BTA_HH_DEBUG 75 APPL_TRACE_DEBUG2("found kdev_cb[%d] hid_handle = %d ", xx, 76 bta_hh_cb.kdev[xx].hid_handle) 77 #endif 78 return xx; 79 } 80 #if BTA_HH_DEBUG 81 else 82 APPL_TRACE_DEBUG4("in_use ? [%d] kdev[%d].hid_handle = %d state = [%d]", 83 bta_hh_cb.kdev[xx].in_use, xx, 84 bta_hh_cb.kdev[xx].hid_handle, 85 bta_hh_cb.kdev[xx].state); 86 #endif 87 } 88 89 /* if no active device match, find a spot for it */ 90 for (xx = 0; xx < BTA_HH_MAX_DEVICE; xx++) 91 { 92 if (!bta_hh_cb.kdev[xx].in_use) 93 { 94 bdcpy(bta_hh_cb.kdev[xx].addr, bda); 95 break; 96 } 97 } 98 /* If device list full, report BTA_HH_IDX_INVALID */ 99 #if BTA_HH_DEBUG 100 APPL_TRACE_DEBUG2("bta_hh_find_cb:: index = %d while max = %d", 101 xx, BTA_HH_MAX_DEVICE); 102 #endif 103 104 if (xx == BTA_HH_MAX_DEVICE) 105 xx = BTA_HH_IDX_INVALID; 106 107 return xx; 108 } 109 110 /******************************************************************************* 111 ** 112 ** Function bta_hh_clean_up_kdev 113 ** 114 ** Description Clean up device control block when device is removed from 115 ** manitainace list, and update control block index map. 116 ** 117 ** Returns void 118 ** 119 *******************************************************************************/ 120 void bta_hh_clean_up_kdev(tBTA_HH_DEV_CB *p_cb) 121 { 122 UINT8 index; 123 124 if (p_cb->hid_handle != BTA_HH_INVALID_HANDLE ) 125 { 126 bta_hh_cb.cb_index[p_cb->hid_handle] = BTA_HH_IDX_INVALID; 127 } 128 129 /* reset device control block */ 130 index = p_cb->index; /* Preserve index for this control block */ 131 132 /* Free buffer for report descriptor info */ 133 utl_freebuf((void **)&p_cb->dscp_info.descriptor.dsc_list); 134 135 memset(p_cb, 0, sizeof (tBTA_HH_DEV_CB)); /* Reset control block */ 136 137 p_cb->index = index; /* Restore index for this control block */ 138 p_cb->state = BTA_HH_IDLE_ST; 139 p_cb->hid_handle = BTA_HH_INVALID_HANDLE; 140 141 } 142 /******************************************************************************* 143 ** 144 ** Function bta_hh_update_di_info 145 ** 146 ** Description Maintain a known device list for BTA HH. 147 ** 148 ** Returns void 149 ** 150 *******************************************************************************/ 151 void bta_hh_update_di_info(tBTA_HH_DEV_CB *p_cb, UINT16 vendor_id, UINT16 product_id, 152 UINT16 version, UINT8 flag) 153 { 154 #if BTA_HH_DEBUG 155 APPL_TRACE_DEBUG3("vendor_id = 0x%2x product_id = 0x%2x version = 0x%2x", 156 vendor_id, product_id, version); 157 #endif 158 p_cb->dscp_info.vendor_id = vendor_id; 159 p_cb->dscp_info.product_id = product_id; 160 p_cb->dscp_info.version = version; 161 } 162 /******************************************************************************* 163 ** 164 ** Function bta_hh_add_device_to_list 165 ** 166 ** Description Maintain a known device list for BTA HH. 167 ** 168 ** Returns void 169 ** 170 *******************************************************************************/ 171 void bta_hh_add_device_to_list(tBTA_HH_DEV_CB *p_cb, UINT8 handle, 172 UINT16 attr_mask, 173 tHID_DEV_DSCP_INFO *p_dscp_info, 174 UINT8 sub_class, 175 UINT16 ssr_max_latency, 176 UINT16 ssr_min_tout, 177 UINT8 app_id) 178 { 179 #if BTA_HH_DEBUG 180 APPL_TRACE_DEBUG1("subclass = 0x%2x", sub_class); 181 #endif 182 183 p_cb->hid_handle = handle; 184 p_cb->in_use = TRUE; 185 p_cb->attr_mask = attr_mask; 186 187 p_cb->sub_class = sub_class; 188 p_cb->app_id = app_id; 189 190 p_cb->dscp_info.ssr_max_latency = ssr_max_latency; 191 p_cb->dscp_info.ssr_min_tout = ssr_min_tout; 192 193 /* store report descriptor info */ 194 if ( p_dscp_info) 195 { 196 utl_freebuf((void **)&p_cb->dscp_info.descriptor.dsc_list); 197 198 if (p_dscp_info->dl_len && 199 (p_cb->dscp_info.descriptor.dsc_list = 200 (UINT8 *)GKI_getbuf(p_dscp_info->dl_len)) != NULL) 201 { 202 p_cb->dscp_info.descriptor.dl_len = p_dscp_info->dl_len; 203 memcpy(p_cb->dscp_info.descriptor.dsc_list, p_dscp_info->dsc_list, 204 p_dscp_info->dl_len); 205 } 206 } 207 return; 208 } 209 210 /******************************************************************************* 211 ** 212 ** Function bta_hh_tod_spt 213 ** 214 ** Description Check to see if this type of device is supported 215 ** 216 ** Returns 217 ** 218 *******************************************************************************/ 219 BOOLEAN bta_hh_tod_spt(tBTA_HH_DEV_CB *p_cb,UINT8 sub_class) 220 { 221 UINT8 xx; 222 UINT8 cod = (sub_class >> 2); /* lower two bits are reserved */ 223 224 for (xx = 0 ; xx < p_bta_hh_cfg->max_devt_spt; xx ++) 225 { 226 if (cod == (UINT8) p_bta_hh_cfg->p_devt_list[xx].tod) 227 { 228 p_cb->app_id = p_bta_hh_cfg->p_devt_list[xx].app_id; 229 #if BTA_HH_DEBUG 230 APPL_TRACE_EVENT1("bta_hh_tod_spt sub_class:0x%x supported", sub_class); 231 #endif 232 return TRUE; 233 } 234 } 235 #if BTA_HH_DEBUG 236 APPL_TRACE_EVENT1("bta_hh_tod_spt sub_class:0x%x NOT supported", sub_class); 237 #endif 238 return FALSE; 239 } 240 241 242 /******************************************************************************* 243 ** 244 ** Function bta_hh_parse_keybd_rpt 245 ** 246 ** Description This utility function parse a boot mode keyboard report. 247 ** 248 ** Returns void 249 ** 250 *******************************************************************************/ 251 void bta_hh_parse_keybd_rpt(tBTA_HH_BOOT_RPT *p_kb_data, UINT8 *p_report, 252 UINT16 report_len) 253 { 254 tBTA_HH_KB_CB *p_kb = &bta_hh_cb.kb_cb; 255 tBTA_HH_KEYBD_RPT *p_data = &p_kb_data->data_rpt.keybd_rpt; 256 257 UINT8 this_char, ctl_shift; 258 UINT16 xx, yy, key_idx = 0; 259 UINT8 this_report[BTA_HH_MAX_RPT_CHARS]; 260 261 #if BTA_HH_DEBUG 262 APPL_TRACE_DEBUG2("bta_hh_parse_keybd_rpt: (report=%p, report_len=%d) called", 263 p_report, report_len); 264 #endif 265 266 if (report_len < 2) 267 return; 268 269 ctl_shift = *p_report++; 270 report_len--; 271 272 if (report_len > BTA_HH_MAX_RPT_CHARS) 273 report_len = BTA_HH_MAX_RPT_CHARS; 274 275 memset (this_report, 0, BTA_HH_MAX_RPT_CHARS); 276 memset (p_data, 0, sizeof(tBTA_HH_KEYBD_RPT)); 277 memcpy (this_report, p_report, report_len); 278 279 /* Take care of shift, control, GUI and alt, modifier keys */ 280 for (xx = 0; xx < BTA_HH_MOD_MAX_KEY; xx ++ ) 281 { 282 if (ctl_shift & bta_hh_mod_key_mask[xx]) 283 { 284 APPL_TRACE_DEBUG1("Mod Key[%02x] pressed", bta_hh_mod_key_mask[xx] ); 285 p_kb->mod_key[xx] = TRUE; 286 } 287 else if (p_kb->mod_key[xx]) 288 { 289 p_kb->mod_key[xx] = FALSE; 290 } 291 /* control key flag is set */ 292 p_data->mod_key[xx] = p_kb->mod_key[xx]; 293 } 294 295 /***************************************************************************/ 296 /* First step is to remove all characters we saw in the last report */ 297 /***************************************************************************/ 298 for (xx = 0; xx < report_len; xx++) 299 { 300 for (yy = 0; yy < BTA_HH_MAX_RPT_CHARS; yy++) 301 { 302 if (this_report[xx] == p_kb->last_report[yy]) 303 { 304 this_report[xx] = 0; 305 } 306 } 307 } 308 /***************************************************************************/ 309 /* Now, process all the characters in the report, up to 6 keycodes */ 310 /***************************************************************************/ 311 for (xx = 0; xx < report_len; xx++) 312 { 313 #if BTA_HH_DEBUG 314 APPL_TRACE_DEBUG1("this_char = %02x", this_report[xx]); 315 #endif 316 if ((this_char = this_report[xx]) == 0) 317 continue; 318 /* take the key code as the report data */ 319 if (this_report[xx] == BTA_HH_KB_CAPS_LOCK) 320 p_kb->caps_lock = p_kb->caps_lock ? FALSE : TRUE; 321 else if (this_report[xx] == BTA_HH_KB_NUM_LOCK) 322 p_kb->num_lock = p_kb->num_lock ? FALSE : TRUE; 323 else 324 p_data->this_char[key_idx ++] = this_char; 325 326 #if BTA_HH_DEBUG 327 APPL_TRACE_DEBUG1("found keycode %02x ", this_report[xx]); 328 #endif 329 p_data->caps_lock = p_kb->caps_lock; 330 p_kb->num_lock = p_kb->num_lock; 331 } 332 333 memset (p_kb->last_report, 0, BTA_HH_MAX_RPT_CHARS); 334 memcpy (p_kb->last_report, p_report, report_len); 335 336 return; 337 } 338 339 /******************************************************************************* 340 ** 341 ** Function bta_hh_parse_mice_rpt 342 ** 343 ** Description This utility function parse a boot mode mouse report. 344 ** 345 ** Returns void 346 ** 347 *******************************************************************************/ 348 void bta_hh_parse_mice_rpt(tBTA_HH_BOOT_RPT *p_mice_data, UINT8 *p_report, 349 UINT16 report_len) 350 { 351 tBTA_HH_MICE_RPT *p_data = &p_mice_data->data_rpt.mice_rpt; 352 #if BTA_HH_DEBUG 353 UINT8 xx; 354 355 APPL_TRACE_DEBUG2("bta_hh_parse_mice_rpt: bta_keybd_rpt_rcvd(report=%p, \ 356 report_len=%d) called", p_report, report_len); 357 #endif 358 359 if (report_len < 3) 360 return; 361 362 if (report_len > BTA_HH_MAX_RPT_CHARS) 363 report_len = BTA_HH_MAX_RPT_CHARS; 364 365 #if BTA_HH_DEBUG 366 for (xx = 0; xx < report_len; xx++) 367 { 368 APPL_TRACE_DEBUG1("this_char = %02x", p_report[xx]); 369 } 370 #endif 371 372 /* only first bytes lower 3 bits valid */ 373 p_data->mouse_button = (p_report[0] & 0x07); 374 375 /* x displacement */ 376 p_data->delta_x = p_report[1]; 377 378 /* y displacement */ 379 p_data->delta_y = p_report[2]; 380 381 #if BTA_HH_DEBUG 382 APPL_TRACE_DEBUG1("mice button: 0x%2x", p_data->mouse_button); 383 APPL_TRACE_DEBUG2("mice move: x = %d y = %d", p_data->delta_x, 384 p_data->delta_y ); 385 #endif 386 387 return; 388 389 } 390 391 /******************************************************************************* 392 ** 393 ** Function bta_hh_read_ssr_param 394 ** 395 ** Description Read the SSR Parameter for the remote device 396 ** 397 ** Returns tBTA_HH_STATUS operation status 398 ** 399 *******************************************************************************/ 400 tBTA_HH_STATUS bta_hh_read_ssr_param(BD_ADDR bd_addr, UINT16 *p_max_ssr_lat, UINT16 *p_min_ssr_tout) 401 { 402 tBTA_HH_STATUS status = BTA_HH_ERR; 403 tBTA_HH_CB *p_cb = &bta_hh_cb; 404 UINT8 i; 405 UINT16 ssr_max_latency; 406 /* lock other GKI task */ 407 GKI_sched_lock(); 408 for (i = 0; i < BTA_HH_MAX_KNOWN; i ++) 409 { 410 if (memcmp(p_cb->kdev[i].addr, bd_addr, BD_ADDR_LEN) == 0) 411 { 412 413 /* if remote device does not have HIDSSRHostMaxLatency attribute in SDP, 414 set SSR max latency default value here. */ 415 if (p_cb->kdev[i].dscp_info.ssr_max_latency == HID_SSR_PARAM_INVALID) 416 { 417 /* The default is calculated as half of link supervision timeout.*/ 418 419 BTM_GetLinkSuperTout(p_cb->kdev[i].addr, &ssr_max_latency) ; 420 ssr_max_latency = BTA_HH_GET_DEF_SSR_MAX_LAT(ssr_max_latency); 421 422 /* per 1.1 spec, if the newly calculated max latency is greater than 423 BTA_HH_SSR_MAX_LATENCY_DEF which is 500ms, use BTA_HH_SSR_MAX_LATENCY_DEF */ 424 if (ssr_max_latency > BTA_HH_SSR_MAX_LATENCY_DEF) 425 ssr_max_latency = BTA_HH_SSR_MAX_LATENCY_DEF; 426 427 * p_max_ssr_lat = ssr_max_latency; 428 } 429 else 430 * p_max_ssr_lat = p_cb->kdev[i].dscp_info.ssr_max_latency; 431 432 if (p_cb->kdev[i].dscp_info.ssr_min_tout == HID_SSR_PARAM_INVALID) 433 * p_min_ssr_tout = BTA_HH_SSR_MIN_TOUT_DEF; 434 else 435 * p_min_ssr_tout = p_cb->kdev[i].dscp_info.ssr_min_tout; 436 437 status = BTA_HH_OK; 438 439 break; 440 } 441 } 442 GKI_sched_unlock(); 443 444 return status; 445 } 446 447 /******************************************************************************* 448 ** 449 ** Function bta_hh_cleanup_disable 450 ** 451 ** Description when disable finished, cleanup control block and send callback 452 ** 453 ** 454 ** Returns void 455 ** 456 *******************************************************************************/ 457 void bta_hh_cleanup_disable(tBTA_HH_STATUS status) 458 { 459 UINT8 xx; 460 /* free buffer in CB holding report descriptors */ 461 for(xx = 0; xx < BTA_HH_MAX_DEVICE; xx ++) 462 { 463 utl_freebuf((void **)&bta_hh_cb.kdev[xx].dscp_info.descriptor.dsc_list); 464 } 465 utl_freebuf((void **)&bta_hh_cb.p_disc_db); 466 467 (* bta_hh_cb.p_cback)(BTA_HH_DISABLE_EVT, (tBTA_HH *)&status); 468 /* all connections are down, no waiting for diconnect */ 469 memset(&bta_hh_cb, 0, sizeof(tBTA_HH_CB)); 470 } 471 472 /******************************************************************************* 473 ** 474 ** Function bta_hh_dev_handle_to_cb_idx 475 ** 476 ** Description convert a HID device handle to the device control block index. 477 ** 478 ** 479 ** Returns UINT8: index of the device control block. 480 ** 481 *******************************************************************************/ 482 UINT8 bta_hh_dev_handle_to_cb_idx(UINT8 dev_handle) 483 { 484 UINT8 index = BTA_HH_IDX_INVALID; 485 486 /* regular HID device checking */ 487 if (dev_handle < BTA_HH_MAX_KNOWN ) 488 index = bta_hh_cb.cb_index[dev_handle]; 489 490 return index; 491 492 } 493 #if BTA_HH_DEBUG 494 /******************************************************************************* 495 ** 496 ** Function bta_hh_trace_dev_db 497 ** 498 ** Description Check to see if this type of device is supported 499 ** 500 ** Returns 501 ** 502 *******************************************************************************/ 503 void bta_hh_trace_dev_db(void) 504 { 505 UINT8 xx; 506 507 APPL_TRACE_DEBUG0("bta_hh_trace_dev_db:: Device DB list********************"); 508 509 for (xx = 0; xx < BTA_HH_MAX_DEVICE; xx++) 510 { 511 APPL_TRACE_DEBUG3("kdev[%d] in_use[%d] handle[%d] ",xx, 512 bta_hh_cb.kdev[xx].in_use, bta_hh_cb.kdev[xx].hid_handle); 513 514 APPL_TRACE_DEBUG4("\t\t\t attr_mask[%04x] state [%d] sub_class[%02x] index = %d", 515 bta_hh_cb.kdev[xx].attr_mask, bta_hh_cb.kdev[xx].state, 516 bta_hh_cb.kdev[xx].sub_class, bta_hh_cb.kdev[xx].index); 517 } 518 APPL_TRACE_DEBUG0("*********************************************************"); 519 } 520 #endif 521 #endif /* HL_INCLUDED */ 522