]> granicus.if.org Git - esp-idf/blob - components/bt/bluedroid/stack/btm/btm_devctl.c
Merge branch 'bugfix/spiram_malloc_reserve_internal_fragments' into 'master'
[esp-idf] / components / bt / bluedroid / stack / btm / btm_devctl.c
1 /******************************************************************************
2  *
3  *  Copyright (C) 1999-2012 Broadcom Corporation
4  *
5  *  Licensed under the Apache License, Version 2.0 (the "License");
6  *  you may not use this file except in compliance with the License.
7  *  You may obtain a copy of the License at:
8  *
9  *  http://www.apache.org/licenses/LICENSE-2.0
10  *
11  *  Unless required by applicable law or agreed to in writing, software
12  *  distributed under the License is distributed on an "AS IS" BASIS,
13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *  See the License for the specific language governing permissions and
15  *  limitations under the License.
16  *
17  ******************************************************************************/
18
19 /******************************************************************************
20  *
21  *  This file contains functions that handle BTM interface functions for the
22  *  Bluetooth device including Rest, HCI buffer size and others
23  *
24  ******************************************************************************/
25
26 #include <stdlib.h>
27 #include <string.h>
28 //#include <stdio.h>
29 #include <stddef.h>
30 #include "common/bt_trace.h"
31 #include "stack/bt_types.h"
32 //#include "bt_utils.h"
33 #include "btm_int.h"
34 #include "stack/btu.h"
35 #include "device/controller.h"
36 #include "hci/hci_layer.h"
37 #include "stack/hcimsgs.h"
38 #include "l2c_int.h"
39 //#include "btcore/include/module.h"
40 //#include "osi/include/osi/thread.h"
41
42 #if BLE_INCLUDED == TRUE
43 #include "gatt_int.h"
44 #endif /* BLE_INCLUDED */
45
46 //extern thread_t *bt_workqueue_thread;
47
48 /********************************************************************************/
49 /*                 L O C A L    D A T A    D E F I N I T I O N S                */
50 /********************************************************************************/
51
52 #ifndef BTM_DEV_RESET_TIMEOUT
53 #define BTM_DEV_RESET_TIMEOUT   4
54 #endif
55
56 #define BTM_DEV_REPLY_TIMEOUT   2    /* 1 second expiration time is not good. Timer may start between 0 and 1 second. */
57 /* if it starts at the very end of the 0 second, timer will expire really easily. */
58
59 #define BTM_INFO_TIMEOUT        5   /* 5 seconds for info response */
60
61 /********************************************************************************/
62 /*              L O C A L    F U N C T I O N     P R O T O T Y P E S            */
63 /********************************************************************************/
64
65 static void btm_decode_ext_features_page (UINT8 page_number, const BD_FEATURES p_features);
66
67 /*******************************************************************************
68 **
69 ** Function         btm_dev_init
70 **
71 ** Description      This function is on the BTM startup
72 **
73 ** Returns          void
74 **
75 *******************************************************************************/
76 void btm_dev_init (void)
77 {
78 #if 0  /* cleared in btm_init; put back in if called from anywhere else! */
79     memset (&btm_cb.devcb, 0, sizeof (tBTM_DEVCB));
80 #endif
81
82     /* Initialize nonzero defaults */
83 #if (BTM_MAX_LOC_BD_NAME_LEN > 0)
84     memset(btm_cb.cfg.bd_name, 0, sizeof(tBTM_LOC_BD_NAME));
85 #endif
86
87     btm_cb.devcb.reset_timer.param  = (TIMER_PARAM_TYPE)TT_DEV_RESET;
88     btm_cb.devcb.rln_timer.param    = (TIMER_PARAM_TYPE)TT_DEV_RLN;
89
90     btm_cb.btm_acl_pkt_types_supported = BTM_ACL_PKT_TYPES_MASK_DH1 + BTM_ACL_PKT_TYPES_MASK_DM1 +
91                                          BTM_ACL_PKT_TYPES_MASK_DH3 + BTM_ACL_PKT_TYPES_MASK_DM3 +
92                                          BTM_ACL_PKT_TYPES_MASK_DH5 + BTM_ACL_PKT_TYPES_MASK_DM5;
93
94     btm_cb.btm_sco_pkt_types_supported = BTM_SCO_PKT_TYPES_MASK_HV1 +
95                                          BTM_SCO_PKT_TYPES_MASK_HV2 +
96                                          BTM_SCO_PKT_TYPES_MASK_HV3 +
97                                          BTM_SCO_PKT_TYPES_MASK_EV3 +
98                                          BTM_SCO_PKT_TYPES_MASK_EV4 +
99                                          BTM_SCO_PKT_TYPES_MASK_EV5;
100 }
101
102
103 /*******************************************************************************
104 **
105 ** Function         btm_db_reset
106 **
107 ** Description      This function is called by BTM_DeviceReset and clears out any
108 **                  pending callbacks for inquiries, discoveries, other pending
109 **                  functions that may be in progress.
110 **
111 ** Returns          void
112 **
113 *******************************************************************************/
114 static void btm_db_reset (void)
115 {
116     tBTM_CMPL_CB    *p_cb;
117     tBTM_STATUS      status = BTM_DEV_RESET;
118
119     btm_inq_db_reset();
120
121     if (btm_cb.devcb.p_rln_cmpl_cb) {
122         p_cb = btm_cb.devcb.p_rln_cmpl_cb;
123         btm_cb.devcb.p_rln_cmpl_cb = NULL;
124
125         if (p_cb) {
126             (*p_cb)((void *) NULL);
127         }
128     }
129
130     if (btm_cb.devcb.p_rssi_cmpl_cb) {
131         p_cb = btm_cb.devcb.p_rssi_cmpl_cb;
132         btm_cb.devcb.p_rssi_cmpl_cb = NULL;
133
134         if (p_cb) {
135             (*p_cb)((tBTM_RSSI_RESULTS *) &status);
136         }
137     }
138 }
139
140 static void reset_complete(void)
141 {
142     const controller_t *controller = controller_get_interface();
143
144     /* Tell L2CAP that all connections are gone */
145     l2cu_device_reset ();
146 #if (SMP_INCLUDED == TRUE)
147     /* Clear current security state */
148     for (int devinx = 0; devinx < BTM_SEC_MAX_DEVICE_RECORDS; devinx++) {
149         btm_cb.sec_dev_rec[devinx].sec_state = BTM_SEC_STATE_IDLE;
150     }
151 #endif  ///SMP_INCLUDED == TRUE
152     /* After the reset controller should restore all parameters to defaults. */
153     btm_cb.btm_inq_vars.inq_counter       = 1;
154     btm_cb.btm_inq_vars.inq_scan_window   = HCI_DEF_INQUIRYSCAN_WINDOW;
155     btm_cb.btm_inq_vars.inq_scan_period   = HCI_DEF_INQUIRYSCAN_INTERVAL;
156     btm_cb.btm_inq_vars.inq_scan_type     = HCI_DEF_SCAN_TYPE;
157
158     btm_cb.btm_inq_vars.page_scan_window  = HCI_DEF_PAGESCAN_WINDOW;
159     btm_cb.btm_inq_vars.page_scan_period  = HCI_DEF_PAGESCAN_INTERVAL;
160     btm_cb.btm_inq_vars.page_scan_type    = HCI_DEF_SCAN_TYPE;
161
162 #if (BLE_INCLUDED == TRUE)
163     btm_cb.ble_ctr_cb.conn_state = BLE_CONN_IDLE;
164     btm_cb.ble_ctr_cb.bg_conn_type = BTM_BLE_CONN_NONE;
165     btm_cb.ble_ctr_cb.p_select_cback = NULL;
166     gatt_reset_bgdev_list();
167     btm_ble_multi_adv_init();
168 #endif
169
170     btm_pm_reset();
171
172     l2c_link_processs_num_bufs(controller->get_acl_buffer_count_classic());
173 #if BTM_SCO_HCI_INCLUDED == TRUE
174     btm_sco_process_num_bufs(controller->get_sco_buffer_count());
175 #endif
176 #if (BLE_INCLUDED == TRUE)
177
178 #if (defined BLE_PRIVACY_SPT && BLE_PRIVACY_SPT == TRUE)
179     /* Set up the BLE privacy settings */
180     if (controller->supports_ble() && controller->supports_ble_privacy() &&
181             controller->get_ble_resolving_list_max_size() > 0) {
182         btm_ble_resolving_list_init(controller->get_ble_resolving_list_max_size());
183         /* set the default random private address timeout */
184         btsnd_hcic_ble_set_rand_priv_addr_timeout(BTM_BLE_PRIVATE_ADDR_INT);
185     }
186 #endif
187
188     if (controller->supports_ble()) {
189         btm_ble_white_list_init(controller->get_ble_white_list_size());
190         l2c_link_processs_ble_num_bufs(controller->get_acl_buffer_count_ble());
191     }
192 #endif
193 #if (SMP_INCLUDED == TRUE)
194     BTM_SetPinType (btm_cb.cfg.pin_type, btm_cb.cfg.pin_code, btm_cb.cfg.pin_code_len);
195 #endif  ///SMP_INCLUDED == TRUE
196     for (int i = 0; i <= controller->get_last_features_classic_index(); i++) {
197         btm_decode_ext_features_page(i, controller->get_features_classic(i)->as_array);
198     }
199
200     btm_report_device_status(BTM_DEV_STATUS_UP);
201 }
202
203 // TODO(zachoverflow): remove this function
204 void BTM_DeviceReset (UNUSED_ATTR tBTM_CMPL_CB *p_cb)
205 {
206     /* Flush all ACL connections */
207     btm_acl_device_down();
208
209     /* Clear the callback, so application would not hang on reset */
210     btm_db_reset();
211
212     /* todo: review the below logic; start_up executes under another task context
213      * reset_complete runs in btu task */
214     controller_get_interface()->start_up();
215     reset_complete();
216 }
217
218 /*******************************************************************************
219 **
220 ** Function         BTM_IsDeviceUp
221 **
222 ** Description      This function is called to check if the device is up.
223 **
224 ** Returns          TRUE if device is up, else FALSE
225 **
226 *******************************************************************************/
227 BOOLEAN BTM_IsDeviceUp (void)
228 {
229     return controller_get_interface()->get_is_ready();
230 }
231
232 /*******************************************************************************
233 **
234 ** Function         btm_dev_timeout
235 **
236 ** Description      This function is called when a timer list entry expires.
237 **
238 ** Returns          void
239 **
240 *******************************************************************************/
241 void btm_dev_timeout (TIMER_LIST_ENT  *p_tle)
242 {
243     TIMER_PARAM_TYPE timer_type = (TIMER_PARAM_TYPE)p_tle->param;
244
245     if (timer_type == (TIMER_PARAM_TYPE)TT_DEV_RLN) {
246         tBTM_CMPL_CB  *p_cb = btm_cb.devcb.p_rln_cmpl_cb;
247
248         btm_cb.devcb.p_rln_cmpl_cb = NULL;
249
250         if (p_cb) {
251             (*p_cb)((void *) NULL);
252         }
253     }
254 }
255
256 /*******************************************************************************
257 **
258 ** Function         btm_decode_ext_features_page
259 **
260 ** Description      This function is decodes a features page.
261 **
262 ** Returns          void
263 **
264 *******************************************************************************/
265 static void btm_decode_ext_features_page (UINT8 page_number, const UINT8 *p_features)
266 {
267     BTM_TRACE_DEBUG ("btm_decode_ext_features_page page: %d", page_number);
268     switch (page_number) {
269     /* Extended (Legacy) Page 0 */
270     case HCI_EXT_FEATURES_PAGE_0:
271
272         /* Create ACL supported packet types mask */
273         btm_cb.btm_acl_pkt_types_supported = (BTM_ACL_PKT_TYPES_MASK_DH1 +
274                                               BTM_ACL_PKT_TYPES_MASK_DM1);
275
276         if (HCI_3_SLOT_PACKETS_SUPPORTED(p_features))
277             btm_cb.btm_acl_pkt_types_supported |= (BTM_ACL_PKT_TYPES_MASK_DH3 +
278                                                    BTM_ACL_PKT_TYPES_MASK_DM3);
279
280         if (HCI_5_SLOT_PACKETS_SUPPORTED(p_features))
281             btm_cb.btm_acl_pkt_types_supported |= (BTM_ACL_PKT_TYPES_MASK_DH5 +
282                                                    BTM_ACL_PKT_TYPES_MASK_DM5);
283
284         /* Add in EDR related ACL types */
285         if (!HCI_EDR_ACL_2MPS_SUPPORTED(p_features)) {
286             btm_cb.btm_acl_pkt_types_supported |= (BTM_ACL_PKT_TYPES_MASK_NO_2_DH1 +
287                                                    BTM_ACL_PKT_TYPES_MASK_NO_2_DH3 +
288                                                    BTM_ACL_PKT_TYPES_MASK_NO_2_DH5);
289         }
290
291         if (!HCI_EDR_ACL_3MPS_SUPPORTED(p_features)) {
292             btm_cb.btm_acl_pkt_types_supported |= (BTM_ACL_PKT_TYPES_MASK_NO_3_DH1 +
293                                                    BTM_ACL_PKT_TYPES_MASK_NO_3_DH3 +
294                                                    BTM_ACL_PKT_TYPES_MASK_NO_3_DH5);
295         }
296
297         /* Check to see if 3 and 5 slot packets are available */
298         if (HCI_EDR_ACL_2MPS_SUPPORTED(p_features) ||
299                 HCI_EDR_ACL_3MPS_SUPPORTED(p_features)) {
300             if (!HCI_3_SLOT_EDR_ACL_SUPPORTED(p_features))
301                 btm_cb.btm_acl_pkt_types_supported |= (BTM_ACL_PKT_TYPES_MASK_NO_2_DH3 +
302                                                        BTM_ACL_PKT_TYPES_MASK_NO_3_DH3);
303
304             if (!HCI_5_SLOT_EDR_ACL_SUPPORTED(p_features))
305                 btm_cb.btm_acl_pkt_types_supported |= (BTM_ACL_PKT_TYPES_MASK_NO_2_DH5 +
306                                                        BTM_ACL_PKT_TYPES_MASK_NO_3_DH5);
307         }
308
309         BTM_TRACE_DEBUG("Local supported ACL packet types: 0x%04x",
310                         btm_cb.btm_acl_pkt_types_supported);
311
312         /* Create (e)SCO supported packet types mask */
313         btm_cb.btm_sco_pkt_types_supported = 0;
314 #if BTM_SCO_INCLUDED == TRUE
315         btm_cb.sco_cb.esco_supported = FALSE;
316 #endif
317         if (HCI_SCO_LINK_SUPPORTED(p_features)) {
318             btm_cb.btm_sco_pkt_types_supported = BTM_SCO_PKT_TYPES_MASK_HV1;
319
320             if (HCI_HV2_PACKETS_SUPPORTED(p_features)) {
321                 btm_cb.btm_sco_pkt_types_supported |= BTM_SCO_PKT_TYPES_MASK_HV2;
322             }
323
324             if (HCI_HV3_PACKETS_SUPPORTED(p_features)) {
325                 btm_cb.btm_sco_pkt_types_supported |= BTM_SCO_PKT_TYPES_MASK_HV3;
326             }
327         }
328
329         if (HCI_ESCO_EV3_SUPPORTED(p_features)) {
330             btm_cb.btm_sco_pkt_types_supported |= BTM_SCO_PKT_TYPES_MASK_EV3;
331         }
332
333         if (HCI_ESCO_EV4_SUPPORTED(p_features)) {
334             btm_cb.btm_sco_pkt_types_supported |= BTM_SCO_PKT_TYPES_MASK_EV4;
335         }
336
337         if (HCI_ESCO_EV5_SUPPORTED(p_features)) {
338             btm_cb.btm_sco_pkt_types_supported |= BTM_SCO_PKT_TYPES_MASK_EV5;
339         }
340 #if BTM_SCO_INCLUDED == TRUE
341         if (btm_cb.btm_sco_pkt_types_supported & BTM_ESCO_LINK_ONLY_MASK) {
342             btm_cb.sco_cb.esco_supported = TRUE;
343
344             /* Add in EDR related eSCO types */
345             if (HCI_EDR_ESCO_2MPS_SUPPORTED(p_features)) {
346                 if (!HCI_3_SLOT_EDR_ESCO_SUPPORTED(p_features)) {
347                     btm_cb.btm_sco_pkt_types_supported |= BTM_SCO_PKT_TYPES_MASK_NO_2_EV5;
348                 }
349             } else {
350                 btm_cb.btm_sco_pkt_types_supported |= (BTM_SCO_PKT_TYPES_MASK_NO_2_EV3 +
351                                                        BTM_SCO_PKT_TYPES_MASK_NO_2_EV5);
352             }
353
354             if (HCI_EDR_ESCO_3MPS_SUPPORTED(p_features)) {
355                 if (!HCI_3_SLOT_EDR_ESCO_SUPPORTED(p_features)) {
356                     btm_cb.btm_sco_pkt_types_supported |= BTM_SCO_PKT_TYPES_MASK_NO_3_EV5;
357                 }
358             } else {
359                 btm_cb.btm_sco_pkt_types_supported |= (BTM_SCO_PKT_TYPES_MASK_NO_3_EV3 +
360                                                        BTM_SCO_PKT_TYPES_MASK_NO_3_EV5);
361             }
362         }
363 #endif
364
365         BTM_TRACE_DEBUG("Local supported SCO packet types: 0x%04x",
366                         btm_cb.btm_sco_pkt_types_supported);
367
368         /* Create Default Policy Settings */
369         if (HCI_SWITCH_SUPPORTED(p_features)) {
370             btm_cb.btm_def_link_policy |= HCI_ENABLE_MASTER_SLAVE_SWITCH;
371         } else {
372             btm_cb.btm_def_link_policy &= ~HCI_ENABLE_MASTER_SLAVE_SWITCH;
373         }
374
375         if (HCI_HOLD_MODE_SUPPORTED(p_features)) {
376             btm_cb.btm_def_link_policy |= HCI_ENABLE_HOLD_MODE;
377         } else {
378             btm_cb.btm_def_link_policy &= ~HCI_ENABLE_HOLD_MODE;
379         }
380
381         if (HCI_SNIFF_MODE_SUPPORTED(p_features)) {
382             btm_cb.btm_def_link_policy |= HCI_ENABLE_SNIFF_MODE;
383         } else {
384             btm_cb.btm_def_link_policy &= ~HCI_ENABLE_SNIFF_MODE;
385         }
386
387         if (HCI_PARK_MODE_SUPPORTED(p_features)) {
388             btm_cb.btm_def_link_policy |= HCI_ENABLE_PARK_MODE;
389         } else {
390             btm_cb.btm_def_link_policy &= ~HCI_ENABLE_PARK_MODE;
391         }
392
393         btm_sec_dev_reset ();
394
395         if (HCI_LMP_INQ_RSSI_SUPPORTED(p_features)) {
396             if (HCI_EXT_INQ_RSP_SUPPORTED(p_features)) {
397                 BTM_SetInquiryMode (BTM_INQ_RESULT_EXTENDED);
398             } else {
399                 BTM_SetInquiryMode (BTM_INQ_RESULT_WITH_RSSI);
400             }
401         }
402
403 #if L2CAP_NON_FLUSHABLE_PB_INCLUDED == TRUE
404         if ( HCI_NON_FLUSHABLE_PB_SUPPORTED(p_features)) {
405             l2cu_set_non_flushable_pbf(TRUE);
406         } else {
407             l2cu_set_non_flushable_pbf(FALSE);
408         }
409 #endif
410         BTM_SetPageScanType (BTM_DEFAULT_SCAN_TYPE);
411         BTM_SetInquiryScanType (BTM_DEFAULT_SCAN_TYPE);
412
413         break;
414
415     /* Extended Page 1 */
416     case HCI_EXT_FEATURES_PAGE_1:
417         /* Nothing to do for page 1 */
418         break;
419
420     /* Extended Page 2 */
421     case HCI_EXT_FEATURES_PAGE_2:
422         /* Nothing to do for page 2 */
423         break;
424
425     default:
426         BTM_TRACE_ERROR("btm_decode_ext_features_page page=%d unknown", page_number);
427         break;
428     }
429 }
430
431 /*******************************************************************************
432 **
433 ** Function         BTM_SetLocalDeviceName
434 **
435 ** Description      This function is called to set the local device name.
436 **
437 ** Returns          status of the operation
438 **
439 *******************************************************************************/
440 tBTM_STATUS BTM_SetLocalDeviceName (char *p_name)
441 {
442     UINT8    *p;
443
444     if (!p_name || !p_name[0] || (strlen ((char *)p_name) > BD_NAME_LEN)) {
445         return (BTM_ILLEGAL_VALUE);
446     }
447
448     if (!controller_get_interface()->get_is_ready()) {
449         return (BTM_DEV_RESET);
450     }
451
452 #if BTM_MAX_LOC_BD_NAME_LEN > 0
453     /* Save the device name if local storage is enabled */
454     p = (UINT8 *)btm_cb.cfg.bd_name;
455     if (p != (UINT8 *)p_name) {
456         BCM_STRNCPY_S(btm_cb.cfg.bd_name, sizeof(btm_cb.cfg.bd_name), p_name, BTM_MAX_LOC_BD_NAME_LEN);
457         btm_cb.cfg.bd_name[BTM_MAX_LOC_BD_NAME_LEN] = '\0';
458     }
459 #else
460     p = (UINT8 *)p_name;
461 #endif
462
463     if (btsnd_hcic_change_name(p)) {
464         return (BTM_CMD_STARTED);
465     } else {
466         return (BTM_NO_RESOURCES);
467     }
468 }
469
470
471
472 /*******************************************************************************
473 **
474 ** Function         BTM_ReadLocalDeviceName
475 **
476 ** Description      This function is called to read the local device name.
477 **
478 ** Returns          status of the operation
479 **                  If success, BTM_SUCCESS is returned and p_name points stored
480 **                              local device name
481 **                  If BTM doesn't store local device name, BTM_NO_RESOURCES is
482 **                              is returned and p_name is set to NULL
483 **
484 *******************************************************************************/
485 tBTM_STATUS BTM_ReadLocalDeviceName (char **p_name)
486 {
487 #if BTM_MAX_LOC_BD_NAME_LEN > 0
488     *p_name = btm_cb.cfg.bd_name;
489     return (BTM_SUCCESS);
490 #else
491     *p_name = NULL;
492     return (BTM_NO_RESOURCES);
493 #endif
494 }
495
496
497 /*******************************************************************************
498 **
499 ** Function         BTM_ReadLocalDeviceNameFromController
500 **
501 ** Description      Get local device name from controller. Do not use cached
502 **                  name (used to get chip-id prior to btm reset complete).
503 **
504 ** Returns          BTM_CMD_STARTED if successful, otherwise an error
505 **
506 *******************************************************************************/
507 tBTM_STATUS BTM_ReadLocalDeviceNameFromController (tBTM_CMPL_CB *p_rln_cmpl_cback)
508 {
509     /* Check if rln already in progress */
510     if (btm_cb.devcb.p_rln_cmpl_cb) {
511         return (BTM_NO_RESOURCES);
512     }
513
514     /* Save callback */
515     btm_cb.devcb.p_rln_cmpl_cb = p_rln_cmpl_cback;
516
517     btsnd_hcic_read_name();
518     btu_start_timer (&btm_cb.devcb.rln_timer, BTU_TTYPE_BTM_DEV_CTL, BTM_DEV_REPLY_TIMEOUT);
519
520     return BTM_CMD_STARTED;
521 }
522
523 /*******************************************************************************
524 **
525 ** Function         btm_read_local_name_complete
526 **
527 ** Description      This function is called when local name read complete.
528 **                  message is received from the HCI.
529 **
530 ** Returns          void
531 **
532 *******************************************************************************/
533 void btm_read_local_name_complete (UINT8 *p, UINT16 evt_len)
534 {
535     tBTM_CMPL_CB   *p_cb = btm_cb.devcb.p_rln_cmpl_cb;
536     UINT8           status;
537     UNUSED(evt_len);
538
539     btu_free_timer (&btm_cb.devcb.rln_timer);
540
541     /* If there was a callback address for read local name, call it */
542     btm_cb.devcb.p_rln_cmpl_cb = NULL;
543
544     if (p_cb) {
545         STREAM_TO_UINT8  (status, p);
546
547         if (status == HCI_SUCCESS) {
548             (*p_cb)(p);
549         } else {
550             (*p_cb)(NULL);
551         }
552     }
553 }
554
555 /*******************************************************************************
556 **
557 ** Function         BTM_SetDeviceClass
558 **
559 ** Description      This function is called to set the local device class
560 **
561 ** Returns          status of the operation
562 **
563 *******************************************************************************/
564 tBTM_STATUS BTM_SetDeviceClass (DEV_CLASS dev_class)
565 {
566     if (!memcmp (btm_cb.devcb.dev_class, dev_class, DEV_CLASS_LEN)) {
567         return (BTM_SUCCESS);
568     }
569
570     memcpy (btm_cb.devcb.dev_class, dev_class, DEV_CLASS_LEN);
571
572     if (!controller_get_interface()->get_is_ready()) {
573         return (BTM_DEV_RESET);
574     }
575
576     if (!btsnd_hcic_write_dev_class (dev_class)) {
577         return (BTM_NO_RESOURCES);
578     }
579
580     return (BTM_SUCCESS);
581 }
582
583
584 /*******************************************************************************
585 **
586 ** Function         BTM_ReadDeviceClass
587 **
588 ** Description      This function is called to read the local device class
589 **
590 ** Returns          pointer to the device class
591 **
592 *******************************************************************************/
593 UINT8 *BTM_ReadDeviceClass (void)
594 {
595     return ((UINT8 *)btm_cb.devcb.dev_class);
596 }
597
598
599 /*******************************************************************************
600 **
601 ** Function         BTM_ReadLocalFeatures
602 **
603 ** Description      This function is called to read the local features
604 **
605 ** Returns          pointer to the local features string
606 **
607 *******************************************************************************/
608 // TODO(zachoverflow): get rid of this function
609 UINT8 *BTM_ReadLocalFeatures (void)
610 {
611     // Discarding const modifier for now, until this function dies
612     return (UINT8 *)controller_get_interface()->get_features_classic(0)->as_array;
613 }
614
615 /*******************************************************************************
616 **
617 ** Function         BTM_RegisterForDeviceStatusNotif
618 **
619 ** Description      This function is called to register for device status
620 **                  change notifications.
621 **
622 **                  If one registration is already there calling function should
623 **                  save the pointer to the function that is return and
624 **                  call it when processing of the event is complete
625 **
626 ** Returns          status of the operation
627 **
628 *******************************************************************************/
629 tBTM_DEV_STATUS_CB *BTM_RegisterForDeviceStatusNotif (tBTM_DEV_STATUS_CB *p_cb)
630 {
631     tBTM_DEV_STATUS_CB *p_prev = btm_cb.devcb.p_dev_status_cb;
632
633     btm_cb.devcb.p_dev_status_cb = p_cb;
634     return (p_prev);
635 }
636
637 /*******************************************************************************
638 **
639 ** Function         BTM_VendorSpecificCommand
640 **
641 ** Description      Send a vendor specific HCI command to the controller.
642 **
643 ** Returns
644 **      BTM_SUCCESS         Command sent. Does not expect command complete
645 **                              event. (command cmpl callback param is NULL)
646 **      BTM_CMD_STARTED     Command sent. Waiting for command cmpl event.
647 **
648 ** Notes
649 **      Opcode will be OR'd with HCI_GRP_VENDOR_SPECIFIC.
650 **
651 *******************************************************************************/
652 tBTM_STATUS BTM_VendorSpecificCommand(UINT16 opcode, UINT8 param_len,
653                                       UINT8 *p_param_buf, tBTM_VSC_CMPL_CB *p_cb)
654 {
655     void *p_buf;
656
657     BTM_TRACE_EVENT ("BTM: BTM_VendorSpecificCommand: Opcode: 0x%04X, ParamLen: %i.",
658                      opcode, param_len);
659
660     /* Allocate a buffer to hold HCI command plus the callback function */
661     if ((p_buf = osi_malloc((UINT16)(sizeof(BT_HDR) + sizeof (tBTM_CMPL_CB *) +
662                                      param_len + HCIC_PREAMBLE_SIZE))) != NULL) {
663         /* Send the HCI command (opcode will be OR'd with HCI_GRP_VENDOR_SPECIFIC) */
664         btsnd_hcic_vendor_spec_cmd (p_buf, opcode, param_len, p_param_buf, (void *)p_cb);
665
666         /* Return value */
667         if (p_cb != NULL) {
668             return (BTM_CMD_STARTED);
669         } else {
670             return (BTM_SUCCESS);
671         }
672     } else {
673         return (BTM_NO_RESOURCES);
674     }
675
676 }
677
678
679 /*******************************************************************************
680 **
681 ** Function         btm_vsc_complete
682 **
683 ** Description      This function is called when local HCI Vendor Specific
684 **                  Command complete message is received from the HCI.
685 **
686 ** Returns          void
687 **
688 *******************************************************************************/
689 void btm_vsc_complete (UINT8 *p, UINT16 opcode, UINT16 evt_len,
690                        tBTM_CMPL_CB *p_vsc_cplt_cback)
691 {
692     tBTM_VSC_CMPL   vcs_cplt_params;
693
694     /* If there was a callback address for vcs complete, call it */
695     if (p_vsc_cplt_cback) {
696         /* Pass paramters to the callback function */
697         vcs_cplt_params.opcode = opcode;        /* Number of bytes in return info */
698         vcs_cplt_params.param_len = evt_len;    /* Number of bytes in return info */
699         vcs_cplt_params.p_param_buf = p;
700         (*p_vsc_cplt_cback)(&vcs_cplt_params);  /* Call the VSC complete callback function */
701     }
702 }
703
704 /*******************************************************************************
705 **
706 ** Function         BTM_RegisterForVSEvents
707 **
708 ** Description      This function is called to register/deregister for vendor
709 **                  specific HCI events.
710 **
711 **                  If is_register=TRUE, then the function will be registered;
712 **                  if is_register=FALSE, then the function will be deregistered.
713 **
714 ** Returns          BTM_SUCCESS if successful,
715 **                  BTM_BUSY if maximum number of callbacks have already been
716 **                           registered.
717 **
718 *******************************************************************************/
719 tBTM_STATUS BTM_RegisterForVSEvents (tBTM_VS_EVT_CB *p_cb, BOOLEAN is_register)
720 {
721     tBTM_STATUS retval = BTM_SUCCESS;
722     UINT8 i, free_idx = BTM_MAX_VSE_CALLBACKS;
723
724     /* See if callback is already registered */
725     for (i = 0; i < BTM_MAX_VSE_CALLBACKS; i++) {
726         if (btm_cb.devcb.p_vend_spec_cb[i] == NULL) {
727             /* Found a free slot. Store index */
728             free_idx = i;
729         } else if (btm_cb.devcb.p_vend_spec_cb[i] == p_cb) {
730             /* Found callback in lookup table. If deregistering, clear the entry. */
731             if (is_register == FALSE) {
732                 btm_cb.devcb.p_vend_spec_cb[i] = NULL;
733                 BTM_TRACE_EVENT("BTM Deregister For VSEvents is successfully");
734             }
735             return (BTM_SUCCESS);
736         }
737     }
738
739     /* Didn't find callback. Add callback to free slot if registering */
740     if (is_register) {
741         if (free_idx < BTM_MAX_VSE_CALLBACKS) {
742             btm_cb.devcb.p_vend_spec_cb[free_idx] = p_cb;
743             BTM_TRACE_EVENT("BTM Register For VSEvents is successfully");
744         } else {
745             /* No free entries available */
746             BTM_TRACE_ERROR ("BTM_RegisterForVSEvents: too many callbacks registered");
747
748             retval = BTM_NO_RESOURCES;
749         }
750     }
751
752     return (retval);
753 }
754
755 /*******************************************************************************
756 **
757 ** Function         btm_vendor_specific_evt
758 **
759 ** Description      Process event HCI_VENDOR_SPECIFIC_EVT
760 **
761 **                  Note: Some controllers do not send command complete, so
762 **                  the callback and busy flag are cleared here also.
763 **
764 ** Returns          void
765 **
766 *******************************************************************************/
767 void btm_vendor_specific_evt (UINT8 *p, UINT8 evt_len)
768 {
769     UINT8 i;
770
771     BTM_TRACE_DEBUG ("BTM Event: Vendor Specific event from controller");
772
773     for (i = 0; i < BTM_MAX_VSE_CALLBACKS; i++) {
774         if (btm_cb.devcb.p_vend_spec_cb[i]) {
775             (*btm_cb.devcb.p_vend_spec_cb[i])(evt_len, p);
776         }
777     }
778 }
779
780
781 /*******************************************************************************
782 **
783 ** Function         BTM_WritePageTimeout
784 **
785 ** Description      Send HCI Write Page Timeout.
786 **
787 ** Returns
788 **      BTM_SUCCESS         Command sent.
789 **      BTM_NO_RESOURCES     If out of resources to send the command.
790 **
791 **
792 *******************************************************************************/
793 tBTM_STATUS BTM_WritePageTimeout(UINT16 timeout)
794 {
795     BTM_TRACE_EVENT ("BTM: BTM_WritePageTimeout: Timeout: %d.", timeout);
796
797     /* Send the HCI command */
798     if (btsnd_hcic_write_page_tout (timeout)) {
799         return (BTM_SUCCESS);
800     } else {
801         return (BTM_NO_RESOURCES);
802     }
803 }
804
805 /*******************************************************************************
806 **
807 ** Function         BTM_WriteVoiceSettings
808 **
809 ** Description      Send HCI Write Voice Settings command.
810 **                  See stack/hcidefs.h for settings bitmask values.
811 **
812 ** Returns
813 **      BTM_SUCCESS         Command sent.
814 **      BTM_NO_RESOURCES     If out of resources to send the command.
815 **
816 **
817 *******************************************************************************/
818 tBTM_STATUS BTM_WriteVoiceSettings(UINT16 settings)
819 {
820     BTM_TRACE_EVENT ("BTM: BTM_WriteVoiceSettings: Settings: 0x%04x.", settings);
821
822     /* Send the HCI command */
823     if (btsnd_hcic_write_voice_settings ((UINT16)(settings & 0x03ff))) {
824         return (BTM_SUCCESS);
825     }
826
827     return (BTM_NO_RESOURCES);
828 }
829
830 /*******************************************************************************
831 **
832 ** Function         BTM_EnableTestMode
833 **
834 ** Description      Send HCI the enable device under test command.
835 **
836 **                  Note: Controller can only be taken out of this mode by
837 **                      resetting the controller.
838 **
839 ** Returns
840 **      BTM_SUCCESS         Command sent.
841 **      BTM_NO_RESOURCES    If out of resources to send the command.
842 **
843 **
844 *******************************************************************************/
845 tBTM_STATUS BTM_EnableTestMode(void)
846 {
847     UINT8   cond;
848
849     BTM_TRACE_EVENT ("BTM: BTM_EnableTestMode");
850
851     /* set auto accept connection as this is needed during test mode */
852     /* Allocate a buffer to hold HCI command */
853     cond = HCI_DO_AUTO_ACCEPT_CONNECT;
854     if (!btsnd_hcic_set_event_filter(HCI_FILTER_CONNECTION_SETUP,
855                                      HCI_FILTER_COND_NEW_DEVICE,
856                                      &cond, sizeof(cond))) {
857         return (BTM_NO_RESOURCES);
858     }
859
860     /* put device to connectable mode */
861     if (!BTM_SetConnectability(BTM_CONNECTABLE, BTM_DEFAULT_CONN_WINDOW,
862                                BTM_DEFAULT_CONN_INTERVAL) == BTM_SUCCESS) {
863         return BTM_NO_RESOURCES;
864     }
865
866     /* put device to discoverable mode */
867     if (!BTM_SetDiscoverability(BTM_GENERAL_DISCOVERABLE, BTM_DEFAULT_DISC_WINDOW,
868                                 BTM_DEFAULT_DISC_INTERVAL) == BTM_SUCCESS) {
869         return BTM_NO_RESOURCES;
870     }
871
872     /* mask off all of event from controller */
873     hci_layer_get_interface()->transmit_command(
874         hci_packet_factory_get_interface()->make_set_event_mask((const bt_event_mask_t *)("\x00\x00\x00\x00\x00\x00\x00\x00")),
875         NULL,
876         NULL,
877         NULL);
878
879     /* Send the HCI command */
880     if (btsnd_hcic_enable_test_mode ()) {
881         return (BTM_SUCCESS);
882     } else {
883         return (BTM_NO_RESOURCES);
884     }
885 }
886
887 /*******************************************************************************
888 **
889 ** Function         BTM_DeleteStoredLinkKey
890 **
891 ** Description      This function is called to delete link key for the specified
892 **                  device addresses from the NVRAM storage attached to the Bluetooth
893 **                  controller.
894 **
895 ** Parameters:      bd_addr      - Addresses of the devices
896 **                  p_cb         - Call back function to be called to return
897 **                                 the results
898 **
899 *******************************************************************************/
900 tBTM_STATUS BTM_DeleteStoredLinkKey(BD_ADDR bd_addr, tBTM_CMPL_CB *p_cb)
901 {
902     BD_ADDR local_bd_addr;
903     BOOLEAN delete_all_flag = FALSE;
904
905     /* Check if the previous command is completed */
906     if (btm_cb.devcb.p_stored_link_key_cmpl_cb) {
907         return (BTM_BUSY);
908     }
909
910     if (!bd_addr) {
911         /* This is to delete all link keys */
912         delete_all_flag = TRUE;
913
914         /* We don't care the BD address. Just pass a non zero pointer */
915         bd_addr = local_bd_addr;
916     }
917
918     BTM_TRACE_EVENT ("BTM: BTM_DeleteStoredLinkKey: delete_all_flag: %s",
919                      delete_all_flag ? "TRUE" : "FALSE");
920
921     /* Send the HCI command */
922     btm_cb.devcb.p_stored_link_key_cmpl_cb = p_cb;
923     if (!btsnd_hcic_delete_stored_key (bd_addr, delete_all_flag)) {
924         return (BTM_NO_RESOURCES);
925     } else {
926         return (BTM_SUCCESS);
927     }
928 }
929
930 /*******************************************************************************
931 **
932 ** Function         btm_delete_stored_link_key_complete
933 **
934 ** Description      This function is called when the command complete message
935 **                  is received from the HCI for the delete stored link key command.
936 **
937 ** Returns          void
938 **
939 *******************************************************************************/
940 void btm_delete_stored_link_key_complete (UINT8 *p)
941 {
942     tBTM_CMPL_CB         *p_cb = btm_cb.devcb.p_stored_link_key_cmpl_cb;
943     tBTM_DELETE_STORED_LINK_KEY_COMPLETE  result;
944
945     /* If there was a callback registered for read stored link key, call it */
946     btm_cb.devcb.p_stored_link_key_cmpl_cb = NULL;
947
948     if (p_cb) {
949         /* Set the call back event to indicate command complete */
950         result.event = BTM_CB_EVT_DELETE_STORED_LINK_KEYS;
951
952         /* Extract the result fields from the HCI event */
953         STREAM_TO_UINT8  (result.status, p);
954         STREAM_TO_UINT16 (result.num_keys, p);
955
956         /* Call the call back and pass the result */
957         (*p_cb)(&result);
958     }
959 }
960
961 /*******************************************************************************
962 **
963 ** Function         btm_report_device_status
964 **
965 ** Description      This function is called when there is a change in the device
966 **                  status. This function will report the new device status to
967 **                  the application
968 **
969 ** Returns          void
970 **
971 *******************************************************************************/
972 void btm_report_device_status (tBTM_DEV_STATUS status)
973 {
974     tBTM_DEV_STATUS_CB *p_cb = btm_cb.devcb.p_dev_status_cb;
975
976     /* Call the call back to pass the device status to application */
977     if (p_cb) {
978         (*p_cb)(status);
979     }
980 }
981
982