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