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