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