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