• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /******************************************************************************
2  *
3  *  Copyright (C) 2008-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 the implementation of the SMP interface used by
22  *  applications that can run over an SMP.
23  *
24  ******************************************************************************/
25 #include <string.h>
26 
27 #include "bt_target.h"
28 #include "bt_utils.h"
29 #include "stack_config.h"
30 
31 #if SMP_INCLUDED == TRUE
32     #include "smp_int.h"
33     #include "smp_api.h"
34     #include "l2cdefs.h"
35     #include "l2c_int.h"
36     #include "btm_int.h"
37     #include "hcimsgs.h"
38 
39     #include "btu.h"
40     #include "p_256_ecc_pp.h"
41 
42 /*******************************************************************************
43 **
44 ** Function         SMP_Init
45 **
46 ** Description      This function initializes the SMP unit.
47 **
48 ** Returns          void
49 **
50 *******************************************************************************/
SMP_Init(void)51 void SMP_Init(void)
52 {
53     memset(&smp_cb, 0, sizeof(tSMP_CB));
54     smp_cb.smp_rsp_timer_ent = alarm_new("smp.smp_rsp_timer_ent");
55     smp_cb.delayed_auth_timer_ent = alarm_new("smp.delayed_auth_timer_ent");
56 
57 #if defined(SMP_INITIAL_TRACE_LEVEL)
58     smp_cb.trace_level = SMP_INITIAL_TRACE_LEVEL;
59 #else
60     smp_cb.trace_level = BT_TRACE_LEVEL_NONE;    /* No traces */
61 #endif
62     SMP_TRACE_EVENT ("%s", __FUNCTION__);
63 
64     smp_l2cap_if_init();
65     /* initialization of P-256 parameters */
66     p_256_init_curve(KEY_LENGTH_DWORDS_P256);
67 
68     /* Initialize failure case for certification */
69     smp_cb.cert_failure = stack_config_get_interface()->get_pts_smp_failure_case();
70     if (smp_cb.cert_failure)
71         SMP_TRACE_ERROR ("%s PTS FAILURE MODE IN EFFECT (CASE %d)", __func__, smp_cb.cert_failure);
72 }
73 
74 
75 /*******************************************************************************
76 **
77 ** Function         SMP_SetTraceLevel
78 **
79 ** Description      This function sets the trace level for SMP.  If called with
80 **                  a value of 0xFF, it simply returns the current trace level.
81 **
82 **                  Input Parameters:
83 **                      level:  The level to set the GATT tracing to:
84 **                      0xff-returns the current setting.
85 **                      0-turns off tracing.
86 **                      >= 1-Errors.
87 **                      >= 2-Warnings.
88 **                      >= 3-APIs.
89 **                      >= 4-Events.
90 **                      >= 5-Debug.
91 **
92 ** Returns          The new or current trace level
93 **
94 *******************************************************************************/
SMP_SetTraceLevel(UINT8 new_level)95 extern UINT8 SMP_SetTraceLevel (UINT8 new_level)
96 {
97     if (new_level != 0xFF)
98         smp_cb.trace_level = new_level;
99 
100     return(smp_cb.trace_level);
101 }
102 
103 
104 /*******************************************************************************
105 **
106 ** Function         SMP_Register
107 **
108 ** Description      This function register for the SMP services callback.
109 **
110 ** Returns          void
111 **
112 *******************************************************************************/
SMP_Register(tSMP_CALLBACK * p_cback)113 BOOLEAN SMP_Register (tSMP_CALLBACK *p_cback)
114 {
115     SMP_TRACE_EVENT ("SMP_Register state=%d", smp_cb.state);
116 
117     if (smp_cb.p_callback != NULL)
118     {
119         SMP_TRACE_ERROR ("SMP_Register: duplicate registration, overwrite it");
120     }
121     smp_cb.p_callback = p_cback;
122 
123     return(TRUE);
124 
125 }
126 
127 /*******************************************************************************
128 **
129 ** Function         SMP_Pair
130 **
131 ** Description      This function call to perform a SMP pairing with peer device.
132 **                  Device support one SMP pairing at one time.
133 **
134 ** Parameters       bd_addr - peer device bd address.
135 **
136 ** Returns          None
137 **
138 *******************************************************************************/
SMP_Pair(BD_ADDR bd_addr)139 tSMP_STATUS SMP_Pair (BD_ADDR bd_addr)
140 {
141     tSMP_CB   *p_cb = &smp_cb;
142     UINT8     status = SMP_PAIR_INTERNAL_ERR;
143 
144     SMP_TRACE_EVENT ("%s state=%d br_state=%d flag=0x%x ",
145                       __FUNCTION__, p_cb->state, p_cb->br_state, p_cb->flags);
146     if (p_cb->state != SMP_STATE_IDLE || p_cb->flags & SMP_PAIR_FLAGS_WE_STARTED_DD ||
147         p_cb->smp_over_br)
148     {
149         /* pending security on going, reject this one */
150         return SMP_BUSY;
151     }
152     else
153     {
154         p_cb->flags = SMP_PAIR_FLAGS_WE_STARTED_DD;
155 
156         memcpy (p_cb->pairing_bda, bd_addr, BD_ADDR_LEN);
157 
158         if (!L2CA_ConnectFixedChnl (L2CAP_SMP_CID, bd_addr))
159         {
160             SMP_TRACE_ERROR("%s: L2C connect fixed channel failed.", __FUNCTION__);
161             smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &status);
162             return status;
163         }
164 
165         return SMP_STARTED;
166     }
167 }
168 
169 /*******************************************************************************
170 **
171 ** Function         SMP_BR_PairWith
172 **
173 ** Description      This function is called to start a SMP pairing over BR/EDR.
174 **                  Device support one SMP pairing at one time.
175 **
176 ** Parameters       bd_addr - peer device bd address.
177 **
178 ** Returns          SMP_STARTED if pairing started, otherwise reason for failure.
179 **
180 *******************************************************************************/
SMP_BR_PairWith(BD_ADDR bd_addr)181 tSMP_STATUS SMP_BR_PairWith (BD_ADDR bd_addr)
182 {
183     tSMP_CB   *p_cb = &smp_cb;
184     UINT8     status = SMP_PAIR_INTERNAL_ERR;
185 
186     SMP_TRACE_EVENT ("%s state=%d br_state=%d flag=0x%x ",
187                       __func__, p_cb->state, p_cb->br_state, p_cb->flags);
188 
189     if (p_cb->state != SMP_STATE_IDLE ||
190         p_cb->smp_over_br ||
191         p_cb->flags & SMP_PAIR_FLAGS_WE_STARTED_DD)
192     {
193         /* pending security on going, reject this one */
194         return SMP_BUSY;
195     }
196 
197     p_cb->role = HCI_ROLE_MASTER;
198     p_cb->flags = SMP_PAIR_FLAGS_WE_STARTED_DD;
199     p_cb->smp_over_br = TRUE;
200 
201     memcpy (p_cb->pairing_bda, bd_addr, BD_ADDR_LEN);
202 
203     if (!L2CA_ConnectFixedChnl (L2CAP_SMP_BR_CID, bd_addr))
204     {
205         SMP_TRACE_ERROR("%s: L2C connect fixed channel failed.",__FUNCTION__);
206         smp_br_state_machine_event(p_cb, SMP_BR_AUTH_CMPL_EVT, &status);
207         return status;
208     }
209 
210     return SMP_STARTED;
211 }
212 
213 /*******************************************************************************
214 **
215 ** Function         SMP_PairCancel
216 **
217 ** Description      This function call to cancel a SMP pairing with peer device.
218 **
219 ** Parameters       bd_addr - peer device bd address.
220 **
221 ** Returns          TRUE - Pairining is cancelled
222 **
223 *******************************************************************************/
SMP_PairCancel(BD_ADDR bd_addr)224 BOOLEAN SMP_PairCancel (BD_ADDR bd_addr)
225 {
226     tSMP_CB   *p_cb = &smp_cb;
227     UINT8     err_code = SMP_PAIR_FAIL_UNKNOWN;
228     BOOLEAN   status = FALSE;
229 
230     // PTS SMP failure test cases
231     if (p_cb->cert_failure == 7)
232         err_code = SMP_PASSKEY_ENTRY_FAIL;
233     else if (p_cb->cert_failure == 8)
234         err_code = SMP_NUMERIC_COMPAR_FAIL;
235 
236     BTM_TRACE_EVENT ("SMP_CancelPair state=%d flag=0x%x ", p_cb->state, p_cb->flags);
237     if ( (p_cb->state != SMP_STATE_IDLE)  &&
238          (!memcmp (p_cb->pairing_bda, bd_addr, BD_ADDR_LEN)) )
239     {
240         p_cb->is_pair_cancel = TRUE;
241         SMP_TRACE_DEBUG("Cancel Pairing: set fail reason Unknown");
242         smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &err_code);
243         status = TRUE;
244     }
245 
246     return status;
247 }
248 /*******************************************************************************
249 **
250 ** Function         SMP_SecurityGrant
251 **
252 ** Description      This function is called to grant security process.
253 **
254 ** Parameters       bd_addr - peer device bd address.
255 **                  res     - result of the operation SMP_SUCCESS if success.
256 **                            Otherwise, SMP_REPEATED_ATTEMPTS is too many attempts.
257 **
258 ** Returns          None
259 **
260 *******************************************************************************/
SMP_SecurityGrant(BD_ADDR bd_addr,UINT8 res)261 void SMP_SecurityGrant(BD_ADDR bd_addr, UINT8 res)
262 {
263     SMP_TRACE_EVENT ("SMP_SecurityGrant ");
264 
265     if (smp_cb.smp_over_br)
266     {
267         if (smp_cb.br_state != SMP_BR_STATE_WAIT_APP_RSP ||
268             smp_cb.cb_evt != SMP_SEC_REQUEST_EVT ||
269             memcmp (smp_cb.pairing_bda, bd_addr, BD_ADDR_LEN))
270         {
271             return;
272         }
273 
274         /* clear the SMP_SEC_REQUEST_EVT event after get grant */
275         /* avoid generating duplicate pair request */
276         smp_cb.cb_evt = 0;
277         smp_br_state_machine_event(&smp_cb, SMP_BR_API_SEC_GRANT_EVT, &res);
278         return;
279     }
280 
281     if (smp_cb.state != SMP_STATE_WAIT_APP_RSP ||
282         smp_cb.cb_evt != SMP_SEC_REQUEST_EVT ||
283         memcmp (smp_cb.pairing_bda, bd_addr, BD_ADDR_LEN))
284         return;
285     /* clear the SMP_SEC_REQUEST_EVT event after get grant */
286     /* avoid generate duplicate pair request */
287     smp_cb.cb_evt = 0;
288     smp_sm_event(&smp_cb, SMP_API_SEC_GRANT_EVT, &res);
289 }
290 
291 /*******************************************************************************
292 **
293 ** Function         SMP_PasskeyReply
294 **
295 ** Description      This function is called after Security Manager submitted
296 **                  passkey request to the application.
297 **
298 ** Parameters:      bd_addr      - Address of the device for which passkey was requested
299 **                  res          - result of the operation SMP_SUCCESS if success
300 **                  passkey - numeric value in the range of
301 **                  BTM_MIN_PASSKEY_VAL(0) - BTM_MAX_PASSKEY_VAL(999999(0xF423F)).
302 **
303 *******************************************************************************/
SMP_PasskeyReply(BD_ADDR bd_addr,UINT8 res,UINT32 passkey)304 void SMP_PasskeyReply (BD_ADDR bd_addr, UINT8 res, UINT32 passkey)
305 {
306     tSMP_CB *p_cb = & smp_cb;
307     UINT8   failure = SMP_PASSKEY_ENTRY_FAIL;
308 
309     SMP_TRACE_EVENT ("SMP_PasskeyReply: Key: %d  Result:%d",
310                       passkey, res);
311 
312     /* If timeout already expired or has been canceled, ignore the reply */
313     if (p_cb->cb_evt != SMP_PASSKEY_REQ_EVT)
314     {
315         SMP_TRACE_WARNING ("SMP_PasskeyReply() - Wrong State: %d", p_cb->state);
316         return;
317     }
318 
319     if (memcmp (bd_addr, p_cb->pairing_bda, BD_ADDR_LEN) != 0)
320     {
321         SMP_TRACE_ERROR ("SMP_PasskeyReply() - Wrong BD Addr");
322         return;
323     }
324 
325     if (btm_find_dev (bd_addr) == NULL)
326     {
327         SMP_TRACE_ERROR ("SMP_PasskeyReply() - no dev CB");
328         return;
329     }
330 
331     if (passkey > BTM_MAX_PASSKEY_VAL || res != SMP_SUCCESS)
332     {
333         SMP_TRACE_WARNING ("SMP_PasskeyReply() - Wrong key len: %d or passkey entry fail", passkey);
334         /* send pairing failure */
335         smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &failure);
336 
337     }
338     else if (p_cb->selected_association_model == SMP_MODEL_SEC_CONN_PASSKEY_ENT)
339     {
340         smp_sm_event(&smp_cb, SMP_SC_KEY_READY_EVT, &passkey);
341     }
342     else
343     {
344         smp_convert_string_to_tk(p_cb->tk, passkey);
345     }
346 
347     return;
348 }
349 
350 /*******************************************************************************
351 **
352 ** Function         SMP_ConfirmReply
353 **
354 ** Description      This function is called after Security Manager submitted
355 **                  numeric comparison request to the application.
356 **
357 ** Parameters:      bd_addr      - Address of the device with which numeric
358 **                                 comparison was requested
359 **                  res          - comparison result SMP_SUCCESS if success
360 **
361 *******************************************************************************/
SMP_ConfirmReply(BD_ADDR bd_addr,UINT8 res)362 void SMP_ConfirmReply (BD_ADDR bd_addr, UINT8 res)
363 {
364     tSMP_CB *p_cb = & smp_cb;
365     UINT8   failure = SMP_NUMERIC_COMPAR_FAIL;
366 
367     SMP_TRACE_EVENT ("%s: Result:%d", __FUNCTION__, res);
368 
369     /* If timeout already expired or has been canceled, ignore the reply */
370     if (p_cb->cb_evt != SMP_NC_REQ_EVT)
371     {
372         SMP_TRACE_WARNING ("%s() - Wrong State: %d", __FUNCTION__,p_cb->state);
373         return;
374     }
375 
376     if (memcmp (bd_addr, p_cb->pairing_bda, BD_ADDR_LEN) != 0)
377     {
378         SMP_TRACE_ERROR ("%s() - Wrong BD Addr",__FUNCTION__);
379         return;
380     }
381 
382     if (btm_find_dev (bd_addr) == NULL)
383     {
384         SMP_TRACE_ERROR ("%s() - no dev CB",__FUNCTION__);
385         return;
386     }
387 
388     if (res != SMP_SUCCESS)
389     {
390         SMP_TRACE_WARNING ("%s() - Numeric Comparison fails",__FUNCTION__);
391         /* send pairing failure */
392         smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &failure);
393     }
394     else
395     {
396         smp_sm_event(p_cb, SMP_SC_NC_OK_EVT, NULL);
397     }
398 }
399 
400 /*******************************************************************************
401 **
402 ** Function         SMP_OobDataReply
403 **
404 ** Description      This function is called to provide the OOB data for
405 **                  SMP in response to SMP_OOB_REQ_EVT
406 **
407 ** Parameters:      bd_addr     - Address of the peer device
408 **                  res         - result of the operation SMP_SUCCESS if success
409 **                  p_data      - simple pairing Randomizer  C.
410 **
411 *******************************************************************************/
SMP_OobDataReply(BD_ADDR bd_addr,tSMP_STATUS res,UINT8 len,UINT8 * p_data)412 void SMP_OobDataReply(BD_ADDR bd_addr, tSMP_STATUS res, UINT8 len, UINT8 *p_data)
413 {
414     tSMP_CB *p_cb = & smp_cb;
415     UINT8   failure = SMP_OOB_FAIL;
416     tSMP_KEY        key;
417 
418     SMP_TRACE_EVENT ("%s State: %d  res:%d", __FUNCTION__, smp_cb.state, res);
419 
420     /* If timeout already expired or has been canceled, ignore the reply */
421     if (p_cb->state != SMP_STATE_WAIT_APP_RSP || p_cb->cb_evt != SMP_OOB_REQ_EVT)
422         return;
423 
424     if (res != SMP_SUCCESS || len == 0 || !p_data)
425     {
426         smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &failure);
427     }
428     else
429     {
430         if (len > BT_OCTET16_LEN)
431             len = BT_OCTET16_LEN;
432 
433         memcpy(p_cb->tk, p_data, len);
434 
435         key.key_type    = SMP_KEY_TYPE_TK;
436         key.p_data      = p_cb->tk;
437 
438         smp_sm_event(&smp_cb, SMP_KEY_READY_EVT, &key);
439     }
440 }
441 
442 /*******************************************************************************
443 **
444 ** Function         SMP_SecureConnectionOobDataReply
445 **
446 ** Description      This function is called to provide the SC OOB data for
447 **                  SMP in response to SMP_SC_OOB_REQ_EVT
448 **
449 ** Parameters:      p_data      - pointer to the data
450 **
451 *******************************************************************************/
SMP_SecureConnectionOobDataReply(UINT8 * p_data)452 void SMP_SecureConnectionOobDataReply(UINT8 *p_data)
453 {
454     tSMP_CB  *p_cb = &smp_cb;
455 
456     UINT8  failure = SMP_OOB_FAIL;
457     tSMP_SC_OOB_DATA  *p_oob = (tSMP_SC_OOB_DATA *) p_data;
458     if (!p_oob)
459     {
460         SMP_TRACE_ERROR("%s received no data",__FUNCTION__);
461         smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &failure);
462         return;
463     }
464 
465     SMP_TRACE_EVENT ("%s req_oob_type: %d, loc_oob_data.present: %d, "
466                        "peer_oob_data.present: %d",
467                        __FUNCTION__, p_cb->req_oob_type, p_oob->loc_oob_data.present,
468                        p_oob->peer_oob_data.present);
469 
470     if (p_cb->state != SMP_STATE_WAIT_APP_RSP || p_cb->cb_evt != SMP_SC_OOB_REQ_EVT)
471         return;
472 
473     BOOLEAN  data_missing = FALSE;
474     switch (p_cb->req_oob_type)
475     {
476         case SMP_OOB_PEER:
477             if (!p_oob->peer_oob_data.present)
478                 data_missing = TRUE;
479             break;
480         case SMP_OOB_LOCAL:
481             if (!p_oob->loc_oob_data.present)
482                 data_missing = TRUE;
483             break;
484         case SMP_OOB_BOTH:
485             if (!p_oob->loc_oob_data.present || !p_oob->peer_oob_data.present)
486                 data_missing = TRUE;
487             break;
488         default:
489             SMP_TRACE_EVENT ("Unexpected OOB data type requested. Fail OOB");
490             data_missing = TRUE;
491             break;
492     }
493 
494     if (data_missing)
495     {
496         smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &failure);
497         return;
498     }
499 
500     p_cb->sc_oob_data = *p_oob;
501 
502     smp_sm_event(&smp_cb, SMP_SC_OOB_DATA_EVT, p_data);
503 }
504 
505 /*******************************************************************************
506 **
507 ** Function         SMP_Encrypt
508 **
509 ** Description      This function is called to encrypt the data with the specified
510 **                  key
511 **
512 ** Parameters:      key                 - Pointer to key key[0] conatins the MSB
513 **                  key_len             - key length
514 **                  plain_text          - Pointer to data to be encrypted
515 **                                        plain_text[0] conatins the MSB
516 **                  pt_len              - plain text length
517 **                  p_out                - output of the encrypted texts
518 **
519 **  Returns         Boolean - request is successful
520 *******************************************************************************/
SMP_Encrypt(UINT8 * key,UINT8 key_len,UINT8 * plain_text,UINT8 pt_len,tSMP_ENC * p_out)521 BOOLEAN SMP_Encrypt (UINT8 *key, UINT8 key_len,
522                      UINT8 *plain_text, UINT8 pt_len,
523                      tSMP_ENC *p_out)
524 
525 {
526     BOOLEAN status=FALSE;
527     status = smp_encrypt_data(key, key_len, plain_text, pt_len, p_out);
528     return status;
529 }
530 
531 /*******************************************************************************
532 **
533 ** Function         SMP_KeypressNotification
534 **
535 ** Description      This function is called to notify Security Manager about Keypress Notification.
536 **
537 ** Parameters:     bd_addr      Address of the device to send keypress notification to
538 **                 value        Keypress notification parameter value
539 **
540 *******************************************************************************/
SMP_KeypressNotification(BD_ADDR bd_addr,UINT8 value)541 void SMP_KeypressNotification (BD_ADDR bd_addr, UINT8 value)
542 {
543     tSMP_CB   *p_cb = &smp_cb;
544 
545     SMP_TRACE_EVENT ("%s: Value: %d", __FUNCTION__,value);
546 
547     if (memcmp (bd_addr, p_cb->pairing_bda, BD_ADDR_LEN) != 0)
548     {
549         SMP_TRACE_ERROR ("%s() - Wrong BD Addr",__FUNCTION__);
550         return;
551     }
552 
553     if (btm_find_dev (bd_addr) == NULL)
554     {
555         SMP_TRACE_ERROR ("%s() - no dev CB",__FUNCTION__);
556         return;
557     }
558 
559     /* Keypress Notification is used by a device with KeyboardOnly IO capabilities */
560     /* during the passkey entry protocol */
561     if (p_cb->local_io_capability != SMP_IO_CAP_IN)
562     {
563         SMP_TRACE_ERROR ("%s() - wrong local IO capabilities %d",
564                           __FUNCTION__, p_cb->local_io_capability);
565         return;
566     }
567 
568     if (p_cb->selected_association_model != SMP_MODEL_SEC_CONN_PASSKEY_ENT)
569     {
570         SMP_TRACE_ERROR ("%s() - wrong protocol %d", __FUNCTION__,
571                          p_cb->selected_association_model);
572         return;
573     }
574 
575     smp_sm_event(p_cb, SMP_KEYPRESS_NOTIFICATION_EVENT, &value);
576 }
577 
578 /*******************************************************************************
579 **
580 ** Function         SMP_CreateLocalSecureConnectionsOobData
581 **
582 ** Description      This function is called to start creation of local SC OOB
583 **                  data set (tSMP_LOC_OOB_DATA).
584 **
585 ** Parameters:      bd_addr      - Address of the device to send OOB data block to
586 **
587 **  Returns         Boolean - TRUE: creation of local SC OOB data set started.
588 *******************************************************************************/
SMP_CreateLocalSecureConnectionsOobData(tBLE_BD_ADDR * addr_to_send_to)589 BOOLEAN SMP_CreateLocalSecureConnectionsOobData (tBLE_BD_ADDR *addr_to_send_to)
590 {
591     tSMP_CB *p_cb = &smp_cb;
592     UINT8   *bd_addr;
593 
594     if (addr_to_send_to == NULL)
595     {
596         SMP_TRACE_ERROR ("%s addr_to_send_to is not provided",__FUNCTION__);
597         return FALSE;
598     }
599 
600     bd_addr = addr_to_send_to->bda;
601 
602     SMP_TRACE_EVENT ("%s addr type: %u,  BDA: %08x%04x,  state: %u, br_state: %u",
603                       __FUNCTION__, addr_to_send_to->type,
604                       (bd_addr[0]<<24)+(bd_addr[1]<<16)+(bd_addr[2]<<8) + bd_addr[3],
605                       (bd_addr[4]<<8)+bd_addr[5],
606                       p_cb->state,
607                       p_cb->br_state);
608 
609     if ((p_cb->state != SMP_STATE_IDLE) || (p_cb->smp_over_br))
610     {
611         SMP_TRACE_WARNING ("%s creation of local OOB data set "\
612             "starts only in IDLE state",__FUNCTION__);
613         return FALSE;
614     }
615 
616     p_cb->sc_oob_data.loc_oob_data.addr_sent_to = *addr_to_send_to;
617     smp_sm_event(p_cb, SMP_CR_LOC_SC_OOB_DATA_EVT, NULL);
618 
619     return TRUE;
620 }
621 
622 #endif /* SMP_INCLUDED */
623