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