Home | History | Annotate | Download | only in hid
      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  ******************************************************************************/
     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  ******************************************************************************/
     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  ******************************************************************************/
     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  ******************************************************************************/
    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 
    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  ******************************************************************************/
    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  ******************************************************************************/
    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  ******************************************************************************/
    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  ******************************************************************************/
    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  ******************************************************************************/
    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  ******************************************************************************/
    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  ******************************************************************************/
    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  ******************************************************************************/
    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  ******************************************************************************/
    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  ******************************************************************************/
    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  ******************************************************************************/
    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  ******************************************************************************/
    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