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