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 /*****************************************************************************
27 ** Constants
28 *****************************************************************************/
29 #define BTA_HH_KB_CTRL_MASK 0x11
30 #define BTA_HH_KB_SHIFT_MASK 0x22
31 #define BTA_HH_KB_ALT_MASK 0x44
32 #define BTA_HH_KB_GUI_MASK 0x88
33
34 #define BTA_HH_KB_CAPS_LOCK 0x39 /* caps lock */
35 #define BTA_HH_KB_NUM_LOCK 0x53 /* num lock */
36
37
38 #define BTA_HH_MAX_RPT_CHARS 8
39
40 static const UINT8 bta_hh_mod_key_mask[BTA_HH_MOD_MAX_KEY] =
41 {
42 BTA_HH_KB_CTRL_MASK,
43 BTA_HH_KB_SHIFT_MASK,
44 BTA_HH_KB_ALT_MASK,
45 BTA_HH_KB_GUI_MASK
46 };
47
48
49 /*******************************************************************************
50 **
51 ** Function bta_hh_find_cb
52 **
53 ** Description Find best available control block according to BD address.
54 **
55 **
56 ** Returns void
57 **
58 *******************************************************************************/
bta_hh_find_cb(BD_ADDR bda)59 UINT8 bta_hh_find_cb(BD_ADDR bda)
60 {
61 UINT8 xx;
62
63 /* See how many active devices there are. */
64 for (xx = 0; xx < BTA_HH_MAX_KNOWN; xx++)
65 {
66 /* check if any active/known devices is a match */
67 if ((!bdcmp (bda, bta_hh_cb.kdev[xx].addr) &&
68 bdcmp(bda, bd_addr_null) != 0) )
69 {
70 #if BTA_HH_DEBUG
71 APPL_TRACE_DEBUG2("found kdev_cb[%d] hid_handle = %d ", xx,
72 bta_hh_cb.kdev[xx].hid_handle)
73 #endif
74 return xx;
75 }
76 #if BTA_HH_DEBUG
77 else
78 APPL_TRACE_DEBUG4("in_use ? [%d] kdev[%d].hid_handle = %d state = [%d]",
79 bta_hh_cb.kdev[xx].in_use, xx,
80 bta_hh_cb.kdev[xx].hid_handle,
81 bta_hh_cb.kdev[xx].state);
82 #endif
83 }
84
85 /* if no active device match, find a spot for it */
86 for (xx = 0; xx < BTA_HH_MAX_KNOWN; xx++)
87 {
88 if (!bta_hh_cb.kdev[xx].in_use)
89 {
90 bdcpy(bta_hh_cb.kdev[xx].addr, bda);
91 break;
92 }
93 }
94 /* If device list full, report BTA_HH_MAX_KNOWN */
95 #if BTA_HH_DEBUG
96 APPL_TRACE_DEBUG2("bta_hh_find_cb:: index = %d while max = %d",
97 xx, BTA_HH_MAX_KNOWN);
98 #endif
99
100 return xx;
101 }
102
103 /*******************************************************************************
104 **
105 ** Function bta_hh_clean_up_kdev
106 **
107 ** Description Clean up device control block when device is removed from
108 ** manitainace list, and update control block index map.
109 **
110 ** Returns void
111 **
112 *******************************************************************************/
bta_hh_clean_up_kdev(tBTA_HH_DEV_CB * p_cb)113 void bta_hh_clean_up_kdev(tBTA_HH_DEV_CB *p_cb)
114 {
115 UINT8 index;
116
117 if (p_cb->hid_handle != BTA_HH_INVALID_HANDLE )
118 bta_hh_cb.cb_index[p_cb->hid_handle] = BTA_HH_MAX_KNOWN;
119
120 /* reset device control block */
121 index = p_cb->index; /* Preserve index for this control block */
122
123 /* Free buffer for report descriptor info */
124 utl_freebuf((void **)&p_cb->dscp_info.descriptor.dsc_list);
125
126 memset(p_cb, 0, sizeof (tBTA_HH_DEV_CB)); /* Reset control block */
127
128 p_cb->index = index; /* Restore index for this control block */
129 p_cb->state = BTA_HH_IDLE_ST;
130 p_cb->hid_handle = BTA_HH_INVALID_HANDLE;
131
132 }
133 /*******************************************************************************
134 **
135 ** Function bta_hh_update_di_info
136 **
137 ** Description Maintain a known device list for BTA HH.
138 **
139 ** Returns void
140 **
141 *******************************************************************************/
bta_hh_update_di_info(tBTA_HH_DEV_CB * p_cb,UINT16 vendor_id,UINT16 product_id,UINT16 version)142 void bta_hh_update_di_info(tBTA_HH_DEV_CB *p_cb, UINT16 vendor_id, UINT16 product_id,
143 UINT16 version)
144 {
145 #if BTA_HH_DEBUG
146 APPL_TRACE_DEBUG3("vendor_id = 0x%2x product_id = 0x%2x version = 0x%2x",
147 vendor_id, product_id, version);
148 #endif
149 p_cb->dscp_info.vendor_id = vendor_id;
150 p_cb->dscp_info.product_id = product_id;
151 p_cb->dscp_info.version = version;
152 }
153 /*******************************************************************************
154 **
155 ** Function bta_hh_add_device_to_list
156 **
157 ** Description Maintain a known device list for BTA HH.
158 **
159 ** Returns void
160 **
161 *******************************************************************************/
bta_hh_add_device_to_list(tBTA_HH_DEV_CB * p_cb,UINT8 handle,UINT16 attr_mask,tHID_DEV_DSCP_INFO * p_dscp_info,UINT8 sub_class,UINT16 ssr_max_latency,UINT16 ssr_min_tout,UINT8 app_id)162 void bta_hh_add_device_to_list(tBTA_HH_DEV_CB *p_cb, UINT8 handle,
163 UINT16 attr_mask,
164 tHID_DEV_DSCP_INFO *p_dscp_info,
165 UINT8 sub_class,
166 UINT16 ssr_max_latency,
167 UINT16 ssr_min_tout,
168 UINT8 app_id)
169 {
170 #if BTA_HH_DEBUG
171 APPL_TRACE_DEBUG1("subclass = 0x%2x", sub_class);
172 #endif
173
174 p_cb->hid_handle = handle;
175 p_cb->in_use = TRUE;
176 p_cb->attr_mask = attr_mask;
177
178 p_cb->sub_class = sub_class;
179 p_cb->app_id = app_id;
180
181 if (ssr_max_latency == HID_SSR_PARAM_INVALID)
182 p_cb->dscp_info.ssr_max_latency = BTA_HH_SSR_MAX_LATENCY_DEF;
183 else
184 p_cb->dscp_info.ssr_max_latency = ssr_max_latency;
185
186 if (ssr_min_tout == HID_SSR_PARAM_INVALID)
187 p_cb->dscp_info.ssr_min_tout = BTA_HH_SSR_MIN_TOUT_DEF;
188 else
189 p_cb->dscp_info.ssr_min_tout = ssr_min_tout;
190
191 /* store report descriptor info */
192 if ( p_dscp_info)
193 {
194 utl_freebuf((void **)&p_cb->dscp_info.descriptor.dsc_list);
195
196 if (p_dscp_info->dl_len &&
197 (p_cb->dscp_info.descriptor.dsc_list =
198 (UINT8 *)GKI_getbuf(p_dscp_info->dl_len)) != NULL)
199 {
200 p_cb->dscp_info.descriptor.dl_len = p_dscp_info->dl_len;
201 memcpy(p_cb->dscp_info.descriptor.dsc_list, p_dscp_info->dsc_list,
202 p_dscp_info->dl_len);
203 }
204 }
205 return;
206 }
207
208 /*******************************************************************************
209 **
210 ** Function bta_hh_tod_spt
211 **
212 ** Description Check to see if this type of device is supported
213 **
214 ** Returns
215 **
216 *******************************************************************************/
bta_hh_tod_spt(tBTA_HH_DEV_CB * p_cb,UINT8 sub_class)217 BOOLEAN bta_hh_tod_spt(tBTA_HH_DEV_CB *p_cb,UINT8 sub_class)
218 {
219 UINT8 xx;
220 UINT8 cod = (sub_class >> 2); /* lower two bits are reserved */
221
222 for (xx = 0 ; xx < p_bta_hh_cfg->max_devt_spt; xx ++)
223 {
224 if (cod == (UINT8) p_bta_hh_cfg->p_devt_list[xx].tod)
225 {
226 p_cb->app_id = p_bta_hh_cfg->p_devt_list[xx].app_id;
227 #if BTA_HH_DEBUG
228 APPL_TRACE_EVENT1("bta_hh_tod_spt sub_class:0x%x supported", sub_class);
229 #endif
230 return TRUE;
231 }
232 }
233 #if BTA_HH_DEBUG
234 APPL_TRACE_EVENT1("bta_hh_tod_spt sub_class:0x%x NOT supported", sub_class);
235 #endif
236 return FALSE;
237 }
238
239
240 /*******************************************************************************
241 **
242 ** Function bta_hh_parse_keybd_rpt
243 **
244 ** Description This utility function parse a boot mode keyboard report.
245 **
246 ** Returns void
247 **
248 *******************************************************************************/
bta_hh_parse_keybd_rpt(tBTA_HH_BOOT_RPT * p_kb_data,UINT8 * p_report,UINT16 report_len)249 void bta_hh_parse_keybd_rpt(tBTA_HH_BOOT_RPT *p_kb_data, UINT8 *p_report,
250 UINT16 report_len)
251 {
252 tBTA_HH_KB_CB *p_kb = &bta_hh_cb.kb_cb;
253 tBTA_HH_KEYBD_RPT *p_data = &p_kb_data->data_rpt.keybd_rpt;
254
255 UINT8 this_char, ctl_shift;
256 UINT16 xx, yy, key_idx = 0;
257 UINT8 this_report[BTA_HH_MAX_RPT_CHARS];
258
259 #if BTA_HH_DEBUG
260 APPL_TRACE_DEBUG2("bta_hh_parse_keybd_rpt: (report=%p, report_len=%d) called",
261 p_report, report_len);
262 #endif
263
264 if (report_len < 2)
265 return;
266
267 ctl_shift = *p_report++;
268 report_len--;
269
270 if (report_len > BTA_HH_MAX_RPT_CHARS)
271 report_len = BTA_HH_MAX_RPT_CHARS;
272
273 memset (this_report, 0, BTA_HH_MAX_RPT_CHARS);
274 memset (p_data, 0, sizeof(tBTA_HH_KEYBD_RPT));
275 memcpy (this_report, p_report, report_len);
276
277 /* Take care of shift, control, GUI and alt, modifier keys */
278 for (xx = 0; xx < BTA_HH_MOD_MAX_KEY; xx ++ )
279 {
280 if (ctl_shift & bta_hh_mod_key_mask[xx])
281 {
282 APPL_TRACE_DEBUG1("Mod Key[%02x] pressed", bta_hh_mod_key_mask[xx] );
283 p_kb->mod_key[xx] = TRUE;
284 }
285 else if (p_kb->mod_key[xx])
286 {
287 p_kb->mod_key[xx] = FALSE;
288 }
289 /* control key flag is set */
290 p_data->mod_key[xx] = p_kb->mod_key[xx];
291 }
292
293 /***************************************************************************/
294 /* First step is to remove all characters we saw in the last report */
295 /***************************************************************************/
296 for (xx = 0; xx < report_len; xx++)
297 {
298 for (yy = 0; yy < BTA_HH_MAX_RPT_CHARS; yy++)
299 {
300 if (this_report[xx] == p_kb->last_report[yy])
301 {
302 this_report[xx] = 0;
303 }
304 }
305 }
306 /***************************************************************************/
307 /* Now, process all the characters in the report, up to 6 keycodes */
308 /***************************************************************************/
309 for (xx = 0; xx < report_len; xx++)
310 {
311 #if BTA_HH_DEBUG
312 APPL_TRACE_DEBUG1("this_char = %02x", this_report[xx]);
313 #endif
314 if ((this_char = this_report[xx]) == 0)
315 continue;
316 /* take the key code as the report data */
317 if (this_report[xx] == BTA_HH_KB_CAPS_LOCK)
318 p_kb->caps_lock = p_kb->caps_lock ? FALSE : TRUE;
319 else if (this_report[xx] == BTA_HH_KB_NUM_LOCK)
320 p_kb->num_lock = p_kb->num_lock ? FALSE : TRUE;
321 else
322 p_data->this_char[key_idx ++] = this_char;
323
324 #if BTA_HH_DEBUG
325 APPL_TRACE_DEBUG1("found keycode %02x ", this_report[xx]);
326 #endif
327 p_data->caps_lock = p_kb->caps_lock;
328 p_kb->num_lock = p_kb->num_lock;
329 }
330
331 memset (p_kb->last_report, 0, BTA_HH_MAX_RPT_CHARS);
332 memcpy (p_kb->last_report, p_report, report_len);
333
334 return;
335 }
336
337 /*******************************************************************************
338 **
339 ** Function bta_hh_parse_mice_rpt
340 **
341 ** Description This utility function parse a boot mode mouse report.
342 **
343 ** Returns void
344 **
345 *******************************************************************************/
bta_hh_parse_mice_rpt(tBTA_HH_BOOT_RPT * p_mice_data,UINT8 * p_report,UINT16 report_len)346 void bta_hh_parse_mice_rpt(tBTA_HH_BOOT_RPT *p_mice_data, UINT8 *p_report,
347 UINT16 report_len)
348 {
349 tBTA_HH_MICE_RPT *p_data = &p_mice_data->data_rpt.mice_rpt;
350 #if BTA_HH_DEBUG
351 UINT8 xx;
352
353 APPL_TRACE_DEBUG2("bta_hh_parse_mice_rpt: bta_keybd_rpt_rcvd(report=%p, \
354 report_len=%d) called", p_report, report_len);
355 #endif
356
357 if (report_len < 3)
358 return;
359
360 if (report_len > BTA_HH_MAX_RPT_CHARS)
361 report_len = BTA_HH_MAX_RPT_CHARS;
362
363 #if BTA_HH_DEBUG
364 for (xx = 0; xx < report_len; xx++)
365 {
366 APPL_TRACE_DEBUG1("this_char = %02x", p_report[xx]);
367 }
368 #endif
369
370 /* only first bytes lower 3 bits valid */
371 p_data->mouse_button = (p_report[0] & 0x07);
372
373 /* x displacement */
374 p_data->delta_x = p_report[1];
375
376 /* y displacement */
377 p_data->delta_y = p_report[2];
378
379 #if BTA_HH_DEBUG
380 APPL_TRACE_DEBUG1("mice button: 0x%2x", p_data->mouse_button);
381 APPL_TRACE_DEBUG2("mice move: x = %d y = %d", p_data->delta_x,
382 p_data->delta_y );
383 #endif
384
385 return;
386
387 }
388
389 #if BTA_HH_DEBUG
390 /*******************************************************************************
391 **
392 ** Function bta_hh_trace_dev_db
393 **
394 ** Description Check to see if this type of device is supported
395 **
396 ** Returns
397 **
398 *******************************************************************************/
bta_hh_trace_dev_db(void)399 void bta_hh_trace_dev_db(void)
400 {
401 UINT8 xx;
402
403 APPL_TRACE_DEBUG0("bta_hh_trace_dev_db:: Device DB list********************");
404
405 for (xx = 0; xx < BTA_HH_MAX_KNOWN; xx++)
406 {
407 APPL_TRACE_DEBUG3("kdev[%d] in_use[%d] handle[%d] ",xx,
408 bta_hh_cb.kdev[xx].in_use, bta_hh_cb.kdev[xx].hid_handle);
409
410 APPL_TRACE_DEBUG4("\t\t\t attr_mask[%04x] state [%d] sub_class[%02x] index = %d",
411 bta_hh_cb.kdev[xx].attr_mask, bta_hh_cb.kdev[xx].state,
412 bta_hh_cb.kdev[xx].sub_class, bta_hh_cb.kdev[xx].index);
413 }
414 APPL_TRACE_DEBUG0("*********************************************************");
415 }
416 #endif
417 #endif /* HL_INCLUDED */
418