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 
19 /******************************************************************************
20  *
21  *  This file contains the HID HOST API in the subsystem of BTA.
22  *
23  ******************************************************************************/
24 
25 #include "common/bt_target.h"
26 
27 #if defined(BTA_HH_INCLUDED) && (BTA_HH_INCLUDED == TRUE)
28 
29 #include <stdlib.h>
30 #include <string.h>
31 #include <stdio.h>
32 
33 #include "bta/bta_hh_api.h"
34 #include "bta_hh_int.h"
35 #include "stack/l2c_api.h"
36 #include "bta/utl.h"
37 
38 #include "osi/allocator.h"
39 
40 /*****************************************************************************
41 **  Constants
42 *****************************************************************************/
43 
44 static const tBTA_SYS_REG bta_hh_reg = {
45     bta_hh_hdl_event,
46     BTA_HhDisable
47 };
48 
49 /*******************************************************************************
50 **
51 ** Function         BTA_HhEnable
52 **
53 ** Description      Enable the HID host.  This function must be called before
54 **                  any other functions in the HID host API are called. When the
55 **                  enable operation is complete the callback function will be
56 **                  called with BTA_HH_ENABLE_EVT.
57 **
58 **
59 ** Returns          void
60 **
61 *******************************************************************************/
BTA_HhEnable(tBTA_SEC sec_mask,tBTA_HH_CBACK * p_cback)62 void BTA_HhEnable(tBTA_SEC sec_mask, tBTA_HH_CBACK *p_cback)
63 {
64     tBTA_HH_API_ENABLE *p_buf;
65 
66     /* register with BTA system manager */
67     bta_sys_register(BTA_ID_HH, &bta_hh_reg);
68 
69     APPL_TRACE_API("%s sec_mask:0x%x p_cback:%p", __func__, sec_mask, p_cback);
70     p_buf = (tBTA_HH_API_ENABLE *)osi_malloc((UINT16)sizeof(tBTA_HH_API_ENABLE));
71 
72     if (p_buf != NULL) {
73         memset(p_buf, 0, sizeof(tBTA_HH_API_ENABLE));
74 
75         p_buf->hdr.event = BTA_HH_API_ENABLE_EVT;
76         p_buf->p_cback = p_cback;
77         p_buf->sec_mask = sec_mask;
78 
79         bta_sys_sendmsg(p_buf);
80     }
81 }
82 
83 /*******************************************************************************
84 **
85 ** Function         BTA_HhDisable
86 **
87 ** Description      Disable the HID host. If the server is currently
88 **                  connected, the connection will be closed.
89 **
90 ** Returns          void
91 **
92 *******************************************************************************/
BTA_HhDisable(void)93 void BTA_HhDisable(void)
94 {
95     BT_HDR  *p_buf;
96 
97     bta_sys_deregister(BTA_ID_HH);
98     if ((p_buf = (BT_HDR *)osi_malloc(sizeof(BT_HDR))) != NULL) {
99         p_buf->event = BTA_HH_API_DISABLE_EVT;
100         bta_sys_sendmsg(p_buf);
101     }
102 }
103 
104 /*******************************************************************************
105 **
106 ** Function         BTA_HhClose
107 **
108 ** Description      Disconnect a connection.
109 **
110 ** Returns          void
111 **
112 *******************************************************************************/
BTA_HhClose(UINT8 dev_handle)113 void BTA_HhClose(UINT8 dev_handle)
114 {
115     BT_HDR    *p_buf;
116 
117     if ((p_buf = (BT_HDR *)osi_malloc((UINT16)sizeof(BT_HDR))) != NULL) {
118         memset(p_buf, 0, sizeof(BT_HDR));
119         p_buf->event            = BTA_HH_API_CLOSE_EVT;
120         p_buf->layer_specific   = (UINT16) dev_handle;
121 
122         bta_sys_sendmsg(p_buf);
123     }
124 }
125 
126 /*******************************************************************************
127 **
128 ** Function         BTA_HhOpen
129 **
130 ** Description      Connect to a device of specified BD address in specified
131 **                  protocol mode and security level.
132 **
133 ** Returns          void
134 **
135 *******************************************************************************/
BTA_HhOpen(BD_ADDR dev_bda,tBTA_HH_PROTO_MODE mode,tBTA_SEC sec_mask)136 void BTA_HhOpen(BD_ADDR dev_bda, tBTA_HH_PROTO_MODE mode, tBTA_SEC sec_mask)
137 {
138     tBTA_HH_API_CONN *p_buf;
139 
140     p_buf = (tBTA_HH_API_CONN *)osi_malloc((UINT16)sizeof(tBTA_HH_API_CONN));
141 
142     if (p_buf != NULL) {
143         memset((void *)p_buf, 0, sizeof(tBTA_HH_API_CONN));
144 
145         p_buf->hdr.event            = BTA_HH_API_OPEN_EVT;
146         p_buf->hdr.layer_specific   = BTA_HH_INVALID_HANDLE;
147         p_buf->sec_mask             = sec_mask;
148         p_buf->mode                 = mode;
149         bdcpy(p_buf->bd_addr, dev_bda);
150 
151         bta_sys_sendmsg((void *)p_buf);
152     } else {
153         APPL_TRACE_ERROR("No resource to send HID host Connect request.");
154     }
155 }
156 
157 /*******************************************************************************
158 **
159 ** Function  bta_hh_snd_write_dev
160 **
161 *******************************************************************************/
bta_hh_snd_write_dev(UINT8 dev_handle,UINT8 t_type,UINT8 param,UINT16 data,UINT8 rpt_id,BT_HDR * p_data)162 static void bta_hh_snd_write_dev(UINT8 dev_handle, UINT8 t_type, UINT8 param,
163                                  UINT16 data, UINT8 rpt_id, BT_HDR  *p_data)
164 {
165     tBTA_HH_CMD_DATA *p_buf;
166     UINT16          len = (UINT16) (sizeof(tBTA_HH_CMD_DATA) );
167 
168     if ((p_buf = (tBTA_HH_CMD_DATA *)osi_malloc(len)) != NULL) {
169         memset(p_buf, 0, sizeof(tBTA_HH_CMD_DATA));
170 
171         p_buf->hdr.event = BTA_HH_API_WRITE_DEV_EVT;
172         p_buf->hdr.layer_specific   = (UINT16) dev_handle;
173         p_buf->t_type   = t_type;
174         p_buf->data     = data;
175         p_buf->param    = param;
176         p_buf->p_data   = p_data;
177         p_buf->rpt_id   = rpt_id;
178 
179         bta_sys_sendmsg(p_buf);
180     }
181 }
182 /*******************************************************************************
183 **
184 ** Function         BTA_HhSetReport
185 **
186 ** Description      send SET_REPORT to device.
187 **
188 ** Parameter        dev_handle: device handle
189 **                  r_type:     report type, could be BTA_HH_RPTT_OUTPUT or
190 **                              BTA_HH_RPTT_FEATURE.
191 ** Returns          void
192 **
193 *******************************************************************************/
BTA_HhSetReport(UINT8 dev_handle,tBTA_HH_RPT_TYPE r_type,BT_HDR * p_data)194 void BTA_HhSetReport(UINT8 dev_handle, tBTA_HH_RPT_TYPE r_type, BT_HDR *p_data)
195 {
196     bta_hh_snd_write_dev(dev_handle, HID_TRANS_SET_REPORT, r_type, 0, 0, p_data);
197 }
198 /*******************************************************************************
199 **
200 ** Function         BTA_HhGetReport
201 **
202 ** Description      Send a GET_REPORT to HID device.
203 **
204 ** Returns          void
205 **
206 *******************************************************************************/
BTA_HhGetReport(UINT8 dev_handle,tBTA_HH_RPT_TYPE r_type,UINT8 rpt_id,UINT16 buf_size)207 void BTA_HhGetReport(UINT8 dev_handle, tBTA_HH_RPT_TYPE r_type, UINT8 rpt_id, UINT16 buf_size)
208 {
209     UINT8 param = (buf_size) ? (r_type | 0x08) : r_type;
210 
211     bta_hh_snd_write_dev(dev_handle, HID_TRANS_GET_REPORT, param,
212                          buf_size, rpt_id, NULL);
213 }
214 /*******************************************************************************
215 **
216 ** Function         BTA_HhSetProtoMode
217 **
218 ** Description      This function set the protocol mode at specified HID handle
219 **
220 ** Returns          void
221 **
222 *******************************************************************************/
BTA_HhSetProtoMode(UINT8 dev_handle,tBTA_HH_PROTO_MODE p_type)223 void BTA_HhSetProtoMode(UINT8 dev_handle, tBTA_HH_PROTO_MODE p_type)
224 {
225     bta_hh_snd_write_dev(dev_handle, HID_TRANS_SET_PROTOCOL, (UINT8)p_type,
226                          0, 0, NULL);
227 }
228 /*******************************************************************************
229 **
230 ** Function         BTA_HhGetProtoMode
231 **
232 ** Description      This function get protocol mode information.
233 **
234 ** Returns          void
235 **
236 *******************************************************************************/
BTA_HhGetProtoMode(UINT8 dev_handle)237 void BTA_HhGetProtoMode(UINT8 dev_handle)
238 {
239     bta_hh_snd_write_dev(dev_handle, HID_TRANS_GET_PROTOCOL, 0, 0, 0, NULL);
240 }
241 /*******************************************************************************
242 **
243 ** Function         BTA_HhSetIdle
244 **
245 ** Description      send SET_IDLE to device.
246 **
247 ** Returns          void
248 **
249 *******************************************************************************/
BTA_HhSetIdle(UINT8 dev_handle,UINT16 idle_rate)250 void BTA_HhSetIdle(UINT8 dev_handle, UINT16 idle_rate)
251 {
252     bta_hh_snd_write_dev(dev_handle, HID_TRANS_SET_IDLE, 0, idle_rate, 0, NULL);
253 }
254 
255 /*******************************************************************************
256 **
257 ** Function         BTA_HhGetIdle
258 **
259 ** Description      Send a GET_IDLE from HID device.
260 **
261 ** Returns          void
262 **
263 *******************************************************************************/
BTA_HhGetIdle(UINT8 dev_handle)264 void BTA_HhGetIdle(UINT8 dev_handle)
265 {
266     bta_hh_snd_write_dev(dev_handle, HID_TRANS_GET_IDLE, 0, 0, 0, NULL);
267 }
268 /*******************************************************************************
269 **
270 ** Function         BTA_HhSendCtrl
271 **
272 ** Description      Send a control command to HID device.
273 **
274 ** Returns          void
275 **
276 *******************************************************************************/
BTA_HhSendCtrl(UINT8 dev_handle,tBTA_HH_TRANS_CTRL_TYPE c_type)277 void BTA_HhSendCtrl(UINT8 dev_handle, tBTA_HH_TRANS_CTRL_TYPE c_type)
278 {
279     bta_hh_snd_write_dev(dev_handle, HID_TRANS_CONTROL, (UINT8)c_type, 0, 0, NULL);
280 }
281 /*******************************************************************************
282 **
283 ** Function         BTA_HhSendData
284 **
285 ** Description      This function send DATA transaction to HID device.
286 **
287 ** Parameter        dev_handle: device handle
288 **                  dev_bda: remote device address
289 **                  p_data: data to be sent in the DATA transaction; or
290 **                          the data to be write into the Output Report of a LE HID
291 **                          device. The report is identified the report ID which is
292 **                          the value of the byte (UINT8 *)(p_buf + 1) + p_buf->offset.
293 **                          p_data->layer_specific needs to be set to the report type,
294 **                          it can be OUTPUT report, or FEATURE report.
295 **
296 ** Returns          void
297 **
298 *******************************************************************************/
BTA_HhSendData(UINT8 dev_handle,BD_ADDR dev_bda,BT_HDR * p_data)299 void BTA_HhSendData(UINT8 dev_handle, BD_ADDR dev_bda, BT_HDR  *p_data)
300 {
301     UNUSED(dev_bda);
302 #if (defined BTA_HH_LE_INCLUDED && BTA_HH_LE_INCLUDED == TRUE)
303     if (p_data->layer_specific != BTA_HH_RPTT_OUTPUT) {
304         APPL_TRACE_ERROR("ERROR! Wrong report type! Write Command only valid for output report!");
305         return;
306     }
307 #endif
308     bta_hh_snd_write_dev(dev_handle, HID_TRANS_DATA, (UINT8)p_data->layer_specific, 0, 0, p_data);
309 }
310 
311 /*******************************************************************************
312 **
313 ** Function         BTA_HhGetDscpInfo
314 **
315 ** Description      Get HID device report descriptor
316 **
317 ** Returns          void
318 **
319 *******************************************************************************/
BTA_HhGetDscpInfo(UINT8 dev_handle)320 void BTA_HhGetDscpInfo(UINT8 dev_handle)
321 {
322     BT_HDR    *p_buf;
323 
324     if ((p_buf = (BT_HDR *)osi_malloc((UINT16)sizeof(BT_HDR))) != NULL) {
325         memset(p_buf, 0, sizeof(BT_HDR));
326         p_buf->event            = BTA_HH_API_GET_DSCP_EVT;
327         p_buf->layer_specific   = (UINT16) dev_handle;
328 
329         bta_sys_sendmsg(p_buf);
330     }
331 }
332 
333 /*******************************************************************************
334 **
335 ** Function         BTA_HhAddDev
336 **
337 ** Description      Add a virtually cabled device into HID-Host device list
338 **                  to manage and assign a device handle for future API call,
339 **                  host applciation call this API at start-up to initialize its
340 **                  virtually cabled devices.
341 **
342 ** Returns          void
343 **
344 *******************************************************************************/
BTA_HhAddDev(BD_ADDR bda,tBTA_HH_ATTR_MASK attr_mask,UINT8 sub_class,UINT8 app_id,tBTA_HH_DEV_DSCP_INFO dscp_info)345 void BTA_HhAddDev(BD_ADDR bda, tBTA_HH_ATTR_MASK attr_mask, UINT8 sub_class,
346                   UINT8 app_id, tBTA_HH_DEV_DSCP_INFO dscp_info)
347 {
348     tBTA_HH_MAINT_DEV    *p_buf;
349     UINT16  len = sizeof(tBTA_HH_MAINT_DEV) + dscp_info.descriptor.dl_len;
350 
351     p_buf = (tBTA_HH_MAINT_DEV *)osi_malloc(len);
352 
353     if (p_buf != NULL) {
354         memset(p_buf, 0, sizeof(tBTA_HH_MAINT_DEV));
355 
356         p_buf->hdr.event            = BTA_HH_API_MAINT_DEV_EVT;
357         p_buf->sub_event            = BTA_HH_ADD_DEV_EVT;
358         p_buf->hdr.layer_specific   = BTA_HH_INVALID_HANDLE;
359 
360         p_buf->attr_mask            = (UINT16) attr_mask;
361         p_buf->sub_class            = sub_class;
362         p_buf->app_id               = app_id;
363         bdcpy(p_buf->bda, bda);
364 
365         memcpy(&p_buf->dscp_info, &dscp_info, sizeof(tBTA_HH_DEV_DSCP_INFO));
366         if ( dscp_info.descriptor.dl_len != 0 && dscp_info.descriptor.dsc_list) {
367             p_buf->dscp_info.descriptor.dl_len =  dscp_info.descriptor.dl_len;
368             p_buf->dscp_info.descriptor.dsc_list = (UINT8 *)(p_buf + 1);
369             memcpy(p_buf->dscp_info.descriptor.dsc_list, dscp_info.descriptor.dsc_list, dscp_info.descriptor.dl_len);
370         } else {
371             p_buf->dscp_info.descriptor.dsc_list = NULL;
372             p_buf->dscp_info.descriptor.dl_len = 0;
373         }
374 
375         bta_sys_sendmsg(p_buf);
376     }
377 }
378 /*******************************************************************************
379 **
380 ** Function         BTA_HhRemoveDev
381 **
382 ** Description      Remove a device from the HID host devices list.
383 **
384 ** Returns          void
385 **
386 *******************************************************************************/
BTA_HhRemoveDev(UINT8 dev_handle)387 void BTA_HhRemoveDev(UINT8 dev_handle )
388 {
389     tBTA_HH_MAINT_DEV    *p_buf;
390 
391     p_buf = (tBTA_HH_MAINT_DEV *)osi_malloc((UINT16)sizeof(tBTA_HH_MAINT_DEV));
392 
393     if (p_buf != NULL) {
394         memset(p_buf, 0, sizeof(tBTA_HH_MAINT_DEV));
395 
396         p_buf->hdr.event            = BTA_HH_API_MAINT_DEV_EVT;
397         p_buf->sub_event            = BTA_HH_RMV_DEV_EVT;
398         p_buf->hdr.layer_specific   = (UINT16) dev_handle;
399 
400         bta_sys_sendmsg(p_buf);
401     }
402 }
403 #if BTA_HH_LE_INCLUDED == TRUE
404 
405 /*******************************************************************************
406 **
407 ** Function         BTA_HhUpdateLeScanParam
408 **
409 ** Description      Update the scan paramteters if connected to a LE hid device as
410 **                  report host.
411 **
412 ** Returns          void
413 **
414 *******************************************************************************/
BTA_HhUpdateLeScanParam(UINT8 dev_handle,UINT16 scan_int,UINT16 scan_win)415 void BTA_HhUpdateLeScanParam(UINT8 dev_handle, UINT16 scan_int, UINT16 scan_win)
416 {
417     tBTA_HH_SCPP_UPDATE    *p_buf;
418 
419     p_buf = (tBTA_HH_SCPP_UPDATE *)osi_malloc((UINT16)sizeof(tBTA_HH_SCPP_UPDATE));
420 
421     if (p_buf != NULL) {
422         memset(p_buf, 0, sizeof(tBTA_HH_SCPP_UPDATE));
423 
424         p_buf->hdr.event            = BTA_HH_API_SCPP_UPDATE_EVT;
425         p_buf->hdr.layer_specific   = (UINT16) dev_handle;
426         p_buf->scan_int             =  scan_int;
427         p_buf->scan_win             =  scan_win;
428 
429         bta_sys_sendmsg(p_buf);
430     }
431 }
432 #endif
433 /*******************************************************************************/
434 /*                          Utility Function                                   */
435 /*******************************************************************************/
436 
437 /*******************************************************************************
438 **
439 ** Function         BTA_HhParseBootRpt
440 **
441 ** Description      This utility function parse a boot mode report.
442 **                  For keyboard report, report data will carry the keycode max
443 **                  up to 6 key press in one report. Application need to convert
444 **                  the keycode into keypress character according to keyboard
445 **                  language.
446 **
447 ** Returns          void
448 **
449 *******************************************************************************/
BTA_HhParseBootRpt(tBTA_HH_BOOT_RPT * p_data,UINT8 * p_report,UINT16 report_len)450 void BTA_HhParseBootRpt(tBTA_HH_BOOT_RPT *p_data, UINT8 *p_report,
451                         UINT16 report_len)
452 {
453     p_data->dev_type = BTA_HH_DEVT_UNKNOWN;
454 
455     if (p_report) {
456         /* first byte is report ID */
457         switch (p_report[0]) {
458         case BTA_HH_KEYBD_RPT_ID: /* key board report ID */
459             p_data->dev_type = p_report[0];
460             bta_hh_parse_keybd_rpt(p_data, p_report + 1, (UINT16)(report_len - 1));
461             break;
462 
463         case BTA_HH_MOUSE_RPT_ID: /* mouse report ID */
464             p_data->dev_type = p_report[0];
465             bta_hh_parse_mice_rpt(p_data, p_report + 1, (UINT16)(report_len - 1));
466             break;
467 
468         default:
469             APPL_TRACE_DEBUG("Unknown boot report: %d", p_report[0]);;
470             break;
471         }
472     }
473 
474     return;
475 }
476 
477 #endif /* BTA_HH_INCLUDED */
478