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