1 /******************************************************************************
2  *
3  *  Copyright (C) 2016 The Android Open Source Project
4  *  Copyright (C) 2002-2012 Broadcom Corporation
5  *
6  *  Licensed under the Apache License, Version 2.0 (the "License");
7  *  you may not use this file except in compliance with the License.
8  *  You may obtain a copy of the License at:
9  *
10  *  http://www.apache.org/licenses/LICENSE-2.0
11  *
12  *  Unless required by applicable law or agreed to in writing, software
13  *  distributed under the License is distributed on an "AS IS" BASIS,
14  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  *  See the License for the specific language governing permissions and
16  *  limitations under the License.
17  *
18  ******************************************************************************/
19 
20 /******************************************************************************
21  *
22  *  This file contains the HID Device API entry points
23  *
24  ******************************************************************************/
25 
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 
30 #include "bt_types.h"
31 #include "btm_api.h"
32 #include "btu.h"
33 #include "hidd_api.h"
34 #include "hidd_int.h"
35 #include "hiddefs.h"
36 
37 #if HID_DYNAMIC_MEMORY == FALSE
38 tHID_DEV_CTB hd_cb;
39 #endif
40 
41 /*******************************************************************************
42  *
43  * Function         HID_DevInit
44  *
45  * Description      Initializes control block
46  *
47  * Returns          void
48  *
49  ******************************************************************************/
HID_DevInit(void)50 void HID_DevInit(void) {
51   uint8_t log_level = hd_cb.trace_level;
52 
53   HIDD_TRACE_API("%s", __func__);
54 
55   memset(&hd_cb, 0, sizeof(tHID_DEV_CTB));
56   hd_cb.trace_level = log_level;
57 }
58 
59 /*******************************************************************************
60  *
61  * Function         HID_DevSetTraceLevel
62  *
63  * Description      This function sets the trace level for HID Dev. If called
64 *with
65  *                  a value of 0xFF, it simply reads the current trace level.
66  *
67  * Returns          the new (current) trace level
68  *
69  ******************************************************************************/
HID_DevSetTraceLevel(uint8_t new_level)70 uint8_t HID_DevSetTraceLevel(uint8_t new_level) {
71   if (new_level != 0xFF) hd_cb.trace_level = new_level;
72 
73   return (hd_cb.trace_level);
74 }
75 
76 /*******************************************************************************
77  *
78  * Function         HID_DevRegister
79  *
80  * Description      Registers HID device with lower layers
81  *
82  * Returns          tHID_STATUS
83  *
84  ******************************************************************************/
HID_DevRegister(tHID_DEV_HOST_CALLBACK * host_cback)85 tHID_STATUS HID_DevRegister(tHID_DEV_HOST_CALLBACK* host_cback) {
86   tHID_STATUS st;
87 
88   HIDD_TRACE_API("%s", __func__);
89 
90   if (hd_cb.reg_flag) return HID_ERR_ALREADY_REGISTERED;
91 
92   if (host_cback == NULL) return HID_ERR_INVALID_PARAM;
93 
94   /* Register with L2CAP */
95   st = hidd_conn_reg();
96   if (st != HID_SUCCESS) return st;
97 
98   hd_cb.callback = host_cback;
99   hd_cb.reg_flag = TRUE;
100 
101   if (hd_cb.pending_data) {
102     osi_free(hd_cb.pending_data);
103     hd_cb.pending_data = NULL;
104   }
105 
106   return (HID_SUCCESS);
107 }
108 
109 /*******************************************************************************
110  *
111  * Function         HID_DevDeregister
112  *
113  * Description      Deregisters HID device with lower layers
114  *
115  * Returns          tHID_STATUS
116  *
117  ******************************************************************************/
HID_DevDeregister(void)118 tHID_STATUS HID_DevDeregister(void) {
119   HIDD_TRACE_API("%s", __func__);
120 
121   if (!hd_cb.reg_flag) return (HID_ERR_NOT_REGISTERED);
122 
123   hidd_conn_dereg();
124 
125   hd_cb.reg_flag = FALSE;
126 
127   return (HID_SUCCESS);
128 }
129 
HID_DevSetSecurityLevel(uint8_t sec_lvl)130 tHID_STATUS HID_DevSetSecurityLevel(uint8_t sec_lvl) {
131   HIDD_TRACE_API("%s", __func__);
132 
133   if (!BTM_SetSecurityLevel(FALSE, "", BTM_SEC_SERVICE_HIDD_SEC_CTRL, sec_lvl,
134                             HID_PSM_CONTROL, BTM_SEC_PROTO_HID, HIDD_SEC_CHN)) {
135     HIDD_TRACE_ERROR("Security Registration 1 failed");
136     return (HID_ERR_NO_RESOURCES);
137   }
138 
139   if (!BTM_SetSecurityLevel(TRUE, "", BTM_SEC_SERVICE_HIDD_SEC_CTRL, sec_lvl,
140                             HID_PSM_CONTROL, BTM_SEC_PROTO_HID, HIDD_SEC_CHN)) {
141     HIDD_TRACE_ERROR("Security Registration 2 failed");
142     return (HID_ERR_NO_RESOURCES);
143   }
144 
145   if (!BTM_SetSecurityLevel(FALSE, "", BTM_SEC_SERVICE_HIDD_NOSEC_CTRL,
146                             BTM_SEC_NONE, HID_PSM_CONTROL, BTM_SEC_PROTO_HID,
147                             HIDD_NOSEC_CHN)) {
148     HIDD_TRACE_ERROR("Security Registration 3 failed");
149     return (HID_ERR_NO_RESOURCES);
150   }
151 
152   if (!BTM_SetSecurityLevel(TRUE, "", BTM_SEC_SERVICE_HIDD_NOSEC_CTRL,
153                             BTM_SEC_NONE, HID_PSM_CONTROL, BTM_SEC_PROTO_HID,
154                             HIDD_NOSEC_CHN)) {
155     HIDD_TRACE_ERROR("Security Registration 4 failed");
156     return (HID_ERR_NO_RESOURCES);
157   }
158 
159   if (!BTM_SetSecurityLevel(TRUE, "", BTM_SEC_SERVICE_HIDD_INTR, BTM_SEC_NONE,
160                             HID_PSM_INTERRUPT, BTM_SEC_PROTO_HID, 0)) {
161     HIDD_TRACE_ERROR("Security Registration 5 failed");
162     return (HID_ERR_NO_RESOURCES);
163   }
164 
165   if (!BTM_SetSecurityLevel(FALSE, "", BTM_SEC_SERVICE_HIDD_INTR, BTM_SEC_NONE,
166                             HID_PSM_INTERRUPT, BTM_SEC_PROTO_HID, 0)) {
167     HIDD_TRACE_ERROR("Security Registration 6 failed");
168     return (HID_ERR_NO_RESOURCES);
169   }
170 
171   return (HID_SUCCESS);
172 }
173 
174 /*******************************************************************************
175  *
176  * Function         HID_DevAddRecord
177  *
178  * Description      Creates SDP record for HID device
179  *
180  * Returns          tHID_STATUS
181  *
182  ******************************************************************************/
HID_DevAddRecord(uint32_t handle,char * p_name,char * p_description,char * p_provider,uint16_t subclass,uint16_t desc_len,uint8_t * p_desc_data)183 tHID_STATUS HID_DevAddRecord(uint32_t handle, char* p_name, char* p_description,
184                              char* p_provider, uint16_t subclass,
185                              uint16_t desc_len, uint8_t* p_desc_data) {
186   bool result = TRUE;
187 
188   HIDD_TRACE_API("%s", __func__);
189 
190   // Service Class ID List
191   if (result) {
192     uint16_t uuid = UUID_SERVCLASS_HUMAN_INTERFACE;
193     result &= SDP_AddServiceClassIdList(handle, 1, &uuid);
194   }
195 
196   // Protocol Descriptor List
197   if (result) {
198     tSDP_PROTOCOL_ELEM proto_list[2];
199 
200     proto_list[0].protocol_uuid = UUID_PROTOCOL_L2CAP;
201     proto_list[0].num_params = 1;
202     proto_list[0].params[0] = BT_PSM_HIDC;
203 
204     proto_list[1].protocol_uuid = UUID_PROTOCOL_HIDP;
205     proto_list[1].num_params = 0;
206 
207     result &= SDP_AddProtocolList(handle, 2, proto_list);
208   }
209 
210   // Language Base Attribute ID List
211   if (result) {
212     result &= SDP_AddLanguageBaseAttrIDList(handle, LANG_ID_CODE_ENGLISH,
213                                             LANG_ID_CHAR_ENCODE_UTF8,
214                                             LANGUAGE_BASE_ID);
215   }
216 
217   // Additional Protocol Descriptor List
218   if (result) {
219     tSDP_PROTO_LIST_ELEM add_proto_list;
220 
221     add_proto_list.num_elems = 2;
222     add_proto_list.list_elem[0].protocol_uuid = UUID_PROTOCOL_L2CAP;
223     add_proto_list.list_elem[0].num_params = 1;
224     add_proto_list.list_elem[0].params[0] = BT_PSM_HIDI;
225     add_proto_list.list_elem[1].protocol_uuid = UUID_PROTOCOL_HIDP;
226     add_proto_list.list_elem[1].num_params = 0;
227 
228     result &= SDP_AddAdditionProtoLists(handle, 1, &add_proto_list);
229   }
230 
231   // Service Name (O)
232   // Service Description (O)
233   // Provider Name (O)
234   if (result) {
235     const char* srv_name = p_name;
236     const char* srv_desc = p_description;
237     const char* provider_name = p_provider;
238 
239     result &= SDP_AddAttribute(handle, ATTR_ID_SERVICE_NAME, TEXT_STR_DESC_TYPE,
240                                strlen(srv_name) + 1, (uint8_t*)srv_name);
241 
242     result &= SDP_AddAttribute(handle, ATTR_ID_SERVICE_DESCRIPTION,
243                                TEXT_STR_DESC_TYPE, strlen(srv_desc) + 1,
244                                (uint8_t*)srv_desc);
245 
246     result &=
247         SDP_AddAttribute(handle, ATTR_ID_PROVIDER_NAME, TEXT_STR_DESC_TYPE,
248                          strlen(provider_name) + 1, (uint8_t*)provider_name);
249   }
250 
251   // Bluetooth Profile Descriptor List
252   if (result) {
253     const uint16_t profile_uuid = UUID_SERVCLASS_HUMAN_INTERFACE;
254     const uint16_t version = 0x0100;
255 
256     result &= SDP_AddProfileDescriptorList(handle, profile_uuid, version);
257   }
258 
259   // HID Parser Version
260   if (result) {
261     uint8_t* p;
262     const uint16_t rel_num = 0x0100;
263     const uint16_t parser_version = 0x0111;
264     const uint16_t prof_ver = 0x0100;
265     const uint8_t dev_subclass = subclass;
266     const uint8_t country_code = 0x21;
267     const uint8_t bool_false = 0x00;
268     const uint8_t bool_true = 0x01;
269     uint16_t temp;
270 
271     p = (uint8_t*)&temp;
272     UINT16_TO_BE_STREAM(p, rel_num);
273     result &= SDP_AddAttribute(handle, ATTR_ID_HID_DEVICE_RELNUM,
274                                UINT_DESC_TYPE, 2, (uint8_t*)&temp);
275 
276     p = (uint8_t*)&temp;
277     UINT16_TO_BE_STREAM(p, parser_version);
278     result &= SDP_AddAttribute(handle, ATTR_ID_HID_PARSER_VERSION,
279                                UINT_DESC_TYPE, 2, (uint8_t*)&temp);
280 
281     result &= SDP_AddAttribute(handle, ATTR_ID_HID_DEVICE_SUBCLASS,
282                                UINT_DESC_TYPE, 1, (uint8_t*)&dev_subclass);
283 
284     result &= SDP_AddAttribute(handle, ATTR_ID_HID_COUNTRY_CODE, UINT_DESC_TYPE,
285                                1, (uint8_t*)&country_code);
286 
287     result &= SDP_AddAttribute(handle, ATTR_ID_HID_VIRTUAL_CABLE,
288                                BOOLEAN_DESC_TYPE, 1, (uint8_t*)&bool_true);
289 
290     result &= SDP_AddAttribute(handle, ATTR_ID_HID_RECONNECT_INITIATE,
291                                BOOLEAN_DESC_TYPE, 1, (uint8_t*)&bool_true);
292 
293     {
294       static uint8_t cdt = 0x22;
295       uint8_t* p_buf;
296       uint8_t seq_len = 4 + desc_len;
297 
298       p_buf = (uint8_t*)osi_malloc(2048);
299 
300       if (p_buf == NULL) {
301         HIDD_TRACE_ERROR("%s: Buffer allocation failure for size = 2048 ",
302                          __func__);
303         return HID_ERR_NOT_REGISTERED;
304       }
305 
306       p = p_buf;
307 
308       UINT8_TO_BE_STREAM(p, (DATA_ELE_SEQ_DESC_TYPE << 3) | SIZE_IN_NEXT_BYTE);
309 
310       UINT8_TO_BE_STREAM(p, seq_len);
311 
312       UINT8_TO_BE_STREAM(p, (UINT_DESC_TYPE << 3) | SIZE_ONE_BYTE);
313       UINT8_TO_BE_STREAM(p, cdt);
314 
315       UINT8_TO_BE_STREAM(p, (TEXT_STR_DESC_TYPE << 3) | SIZE_IN_NEXT_BYTE);
316       UINT8_TO_BE_STREAM(p, desc_len);
317       ARRAY_TO_BE_STREAM(p, p_desc_data, (int)desc_len);
318 
319       result &= SDP_AddAttribute(handle, ATTR_ID_HID_DESCRIPTOR_LIST,
320                                  DATA_ELE_SEQ_DESC_TYPE, p - p_buf, p_buf);
321 
322       osi_free(p_buf);
323     }
324 
325     {
326       uint8_t lang_buf[8];
327       p = lang_buf;
328       uint8_t seq_len = 6;
329       uint16_t lang_english = 0x0409;
330       UINT8_TO_BE_STREAM(p, (DATA_ELE_SEQ_DESC_TYPE << 3) | SIZE_IN_NEXT_BYTE);
331       UINT8_TO_BE_STREAM(p, seq_len);
332       UINT8_TO_BE_STREAM(p, (UINT_DESC_TYPE << 3) | SIZE_TWO_BYTES);
333       UINT16_TO_BE_STREAM(p, lang_english);
334       UINT8_TO_BE_STREAM(p, (UINT_DESC_TYPE << 3) | SIZE_TWO_BYTES);
335       UINT16_TO_BE_STREAM(p, LANGUAGE_BASE_ID);
336       result &=
337           SDP_AddAttribute(handle, ATTR_ID_HID_LANGUAGE_ID_BASE,
338                            DATA_ELE_SEQ_DESC_TYPE, p - lang_buf, lang_buf);
339     }
340 
341     result &= SDP_AddAttribute(handle, ATTR_ID_HID_BATTERY_POWER,
342                                BOOLEAN_DESC_TYPE, 1, (uint8_t*)&bool_true);
343 
344     result &= SDP_AddAttribute(handle, ATTR_ID_HID_REMOTE_WAKE,
345                                BOOLEAN_DESC_TYPE, 1, (uint8_t*)&bool_false);
346 
347     result &= SDP_AddAttribute(handle, ATTR_ID_HID_NORMALLY_CONNECTABLE,
348                                BOOLEAN_DESC_TYPE, 1, (uint8_t*)&bool_true);
349 
350     result &= SDP_AddAttribute(handle, ATTR_ID_HID_BOOT_DEVICE,
351                                BOOLEAN_DESC_TYPE, 1, (uint8_t*)&bool_true);
352 
353     p = (uint8_t*)&temp;
354     UINT16_TO_BE_STREAM(p, prof_ver);
355     result &= SDP_AddAttribute(handle, ATTR_ID_HID_PROFILE_VERSION,
356                                UINT_DESC_TYPE, 2, (uint8_t*)&temp);
357   }
358 
359   if (result) {
360     uint16_t browse_group = UUID_SERVCLASS_PUBLIC_BROWSE_GROUP;
361     result &= SDP_AddUuidSequence(handle, ATTR_ID_BROWSE_GROUP_LIST, 1,
362                                   &browse_group);
363   }
364 
365   if (!result) {
366     HIDD_TRACE_ERROR("%s: failed to complete SDP record", __func__);
367 
368     return HID_ERR_NOT_REGISTERED;
369   }
370 
371   return HID_SUCCESS;
372 }
373 
374 /*******************************************************************************
375  *
376  * Function         HID_DevSendReport
377  *
378  * Description      Sends report
379  *
380  * Returns          tHID_STATUS
381  *
382  ******************************************************************************/
HID_DevSendReport(uint8_t channel,uint8_t type,uint8_t id,uint16_t len,uint8_t * p_data)383 tHID_STATUS HID_DevSendReport(uint8_t channel, uint8_t type, uint8_t id,
384                               uint16_t len, uint8_t* p_data) {
385   HIDD_TRACE_VERBOSE("%s: channel=%d type=%d id=%d len=%d", __func__, channel,
386                      type, id, len);
387 
388   if (channel == HID_CHANNEL_CTRL) {
389     return hidd_conn_send_data(HID_CHANNEL_CTRL, HID_TRANS_DATA, type, id, len,
390                                p_data);
391   }
392 
393   if (channel == HID_CHANNEL_INTR && type == HID_PAR_REP_TYPE_INPUT) {
394     // on INTR we can only send INPUT
395     return hidd_conn_send_data(HID_CHANNEL_INTR, HID_TRANS_DATA,
396                                HID_PAR_REP_TYPE_INPUT, id, len, p_data);
397   }
398 
399   return HID_ERR_INVALID_PARAM;
400 }
401 
402 /*******************************************************************************
403  *
404  * Function         HID_DevVirtualCableUnplug
405  *
406  * Description      Sends Virtual Cable Unplug
407  *
408  * Returns          tHID_STATUS
409  *
410  ******************************************************************************/
HID_DevVirtualCableUnplug(void)411 tHID_STATUS HID_DevVirtualCableUnplug(void) {
412   HIDD_TRACE_API("%s", __func__);
413 
414   return hidd_conn_send_data(HID_CHANNEL_CTRL, HID_TRANS_CONTROL,
415                              HID_PAR_CONTROL_VIRTUAL_CABLE_UNPLUG, 0, 0, NULL);
416 }
417 
418 /*******************************************************************************
419  *
420  * Function         HID_DevPlugDevice
421  *
422  * Description      Establishes virtual cable to given host
423  *
424  * Returns          tHID_STATUS
425  *
426  ******************************************************************************/
HID_DevPlugDevice(BD_ADDR addr)427 tHID_STATUS HID_DevPlugDevice(BD_ADDR addr) {
428   hd_cb.device.in_use = TRUE;
429   memcpy(hd_cb.device.addr, addr, sizeof(BD_ADDR));
430 
431   return HID_SUCCESS;
432 }
433 
434 /*******************************************************************************
435  *
436  * Function         HID_DevUnplugDevice
437  *
438  * Description      Unplugs virtual cable from given host
439  *
440  * Returns          tHID_STATUS
441  *
442  ******************************************************************************/
HID_DevUnplugDevice(BD_ADDR addr)443 tHID_STATUS HID_DevUnplugDevice(BD_ADDR addr) {
444   if (!memcmp(hd_cb.device.addr, addr, sizeof(BD_ADDR))) {
445     hd_cb.device.in_use = FALSE;
446     hd_cb.device.conn.conn_state = HID_CONN_STATE_UNUSED;
447     hd_cb.device.conn.ctrl_cid = 0;
448     hd_cb.device.conn.intr_cid = 0;
449   }
450 
451   return HID_SUCCESS;
452 }
453 
454 /*******************************************************************************
455  *
456  * Function         HID_DevConnect
457  *
458  * Description      Connects to device
459  *
460  * Returns          tHID_STATUS
461  *
462  ******************************************************************************/
HID_DevConnect(void)463 tHID_STATUS HID_DevConnect(void) {
464   if (!hd_cb.reg_flag) {
465     return HID_ERR_NOT_REGISTERED;
466   }
467 
468   if (!hd_cb.device.in_use) {
469     return HID_ERR_INVALID_PARAM;
470   }
471 
472   if (hd_cb.device.state != HIDD_DEV_NO_CONN) {
473     return HID_ERR_ALREADY_CONN;
474   }
475 
476   return hidd_conn_initiate();
477 }
478 
479 /*******************************************************************************
480  *
481  * Function         HID_DevDisconnect
482  *
483  * Description      Disconnects from device
484  *
485  * Returns          tHID_STATUS
486  *
487  ******************************************************************************/
HID_DevDisconnect(void)488 tHID_STATUS HID_DevDisconnect(void) {
489   if (!hd_cb.reg_flag) {
490     return HID_ERR_NOT_REGISTERED;
491   }
492 
493   if (!hd_cb.device.in_use) {
494     return HID_ERR_INVALID_PARAM;
495   }
496 
497   if (hd_cb.device.state == HIDD_DEV_NO_CONN) {
498     /* If we are still trying to connect, just close the connection. */
499     if (hd_cb.device.conn.conn_state != HID_CONN_STATE_UNUSED) {
500       tHID_STATUS ret = hidd_conn_disconnect();
501       hd_cb.device.conn.conn_state = HID_CONN_STATE_UNUSED;
502       hd_cb.callback(hd_cb.device.addr, HID_DHOST_EVT_CLOSE,
503                      HID_ERR_DISCONNECTING, NULL);
504       return ret;
505     }
506     return HID_ERR_NO_CONNECTION;
507   }
508 
509   return hidd_conn_disconnect();
510 }
511 
512 /*******************************************************************************
513  *
514  * Function         HID_DevSetIncomingPolicy
515  *
516  * Description      Sets policy for incoming connections (allowed/disallowed)
517  *
518  * Returns          tHID_STATUS
519  *
520  ******************************************************************************/
HID_DevSetIncomingPolicy(bool allow)521 tHID_STATUS HID_DevSetIncomingPolicy(bool allow) {
522   hd_cb.allow_incoming = allow;
523 
524   return HID_SUCCESS;
525 }
526 
527 /*******************************************************************************
528  *
529  * Function         HID_DevReportError
530  *
531  * Description      Reports error for Set Report via HANDSHAKE
532  *
533  * Returns          tHID_STATUS
534  *
535  ******************************************************************************/
HID_DevReportError(uint8_t error)536 tHID_STATUS HID_DevReportError(uint8_t error) {
537   uint8_t handshake_param;
538 
539   HIDD_TRACE_API("%s: error = %d", __func__, error);
540 
541   switch (error) {
542     case HID_PAR_HANDSHAKE_RSP_SUCCESS:
543     case HID_PAR_HANDSHAKE_RSP_NOT_READY:
544     case HID_PAR_HANDSHAKE_RSP_ERR_INVALID_REP_ID:
545     case HID_PAR_HANDSHAKE_RSP_ERR_UNSUPPORTED_REQ:
546     case HID_PAR_HANDSHAKE_RSP_ERR_INVALID_PARAM:
547     case HID_PAR_HANDSHAKE_RSP_ERR_UNKNOWN:
548     case HID_PAR_HANDSHAKE_RSP_ERR_FATAL:
549       handshake_param = error;
550       break;
551     default:
552       handshake_param = HID_PAR_HANDSHAKE_RSP_ERR_UNKNOWN;
553       break;
554   }
555 
556   return hidd_conn_send_data(0, HID_TRANS_HANDSHAKE, handshake_param, 0, 0,
557                              NULL);
558 }
559 
560 /*******************************************************************************
561  *
562  * Function         HID_DevGetDevice
563  *
564  * Description      Returns the BD Address of virtually cabled device
565  *
566  * Returns          tHID_STATUS
567  *
568  ******************************************************************************/
HID_DevGetDevice(BD_ADDR * addr)569 tHID_STATUS HID_DevGetDevice(BD_ADDR* addr) {
570   HIDD_TRACE_API("%s", __func__);
571 
572   if (hd_cb.device.in_use) {
573     memcpy(addr, hd_cb.device.addr, sizeof(BD_ADDR));
574   } else {
575     return HID_ERR_NOT_REGISTERED;
576   }
577 
578   return HID_SUCCESS;
579 }
580 
581 /*******************************************************************************
582  *
583  * Function         HID_DevSetIncomingQos
584  *
585  * Description      Sets Incoming QoS values for Interrupt L2CAP Channel
586  *
587  * Returns          tHID_STATUS
588  *
589  ******************************************************************************/
HID_DevSetIncomingQos(uint8_t service_type,uint32_t token_rate,uint32_t token_bucket_size,uint32_t peak_bandwidth,uint32_t latency,uint32_t delay_variation)590 tHID_STATUS HID_DevSetIncomingQos(uint8_t service_type, uint32_t token_rate,
591                                   uint32_t token_bucket_size,
592                                   uint32_t peak_bandwidth, uint32_t latency,
593                                   uint32_t delay_variation) {
594   HIDD_TRACE_API("%s", __func__);
595 
596   hd_cb.use_in_qos = TRUE;
597 
598   hd_cb.in_qos.service_type = service_type;
599   hd_cb.in_qos.token_rate = token_rate;
600   hd_cb.in_qos.token_bucket_size = token_bucket_size;
601   hd_cb.in_qos.peak_bandwidth = peak_bandwidth;
602   hd_cb.in_qos.latency = latency;
603   hd_cb.in_qos.delay_variation = delay_variation;
604 
605   return HID_SUCCESS;
606 }
607 
608 /*******************************************************************************
609  *
610  * Function         HID_DevSetOutgoingQos
611  *
612  * Description      Sets Outgoing QoS values for Interrupt L2CAP Channel
613  *
614  * Returns          tHID_STATUS
615  *
616  ******************************************************************************/
HID_DevSetOutgoingQos(uint8_t service_type,uint32_t token_rate,uint32_t token_bucket_size,uint32_t peak_bandwidth,uint32_t latency,uint32_t delay_variation)617 tHID_STATUS HID_DevSetOutgoingQos(uint8_t service_type, uint32_t token_rate,
618                                   uint32_t token_bucket_size,
619                                   uint32_t peak_bandwidth, uint32_t latency,
620                                   uint32_t delay_variation) {
621   HIDD_TRACE_API("%s", __func__);
622 
623   hd_cb.l2cap_intr_cfg.qos_present = TRUE;
624 
625   hd_cb.l2cap_intr_cfg.qos.service_type = service_type;
626   hd_cb.l2cap_intr_cfg.qos.token_rate = token_rate;
627   hd_cb.l2cap_intr_cfg.qos.token_bucket_size = token_bucket_size;
628   hd_cb.l2cap_intr_cfg.qos.peak_bandwidth = peak_bandwidth;
629   hd_cb.l2cap_intr_cfg.qos.latency = latency;
630   hd_cb.l2cap_intr_cfg.qos.delay_variation = delay_variation;
631 
632   return HID_SUCCESS;
633 }
634