Пример #1
0
void zb_nwk_mesh_routing_init() 
{
  TRACE_MSG(TRACE_NWK1, ">> mesh_r_init", (FMT__0));

  /* Check for expired route discovery entries */
  TRACE_MSG(TRACE_NWK1, "schd r disc expiry f %d", (FMT__D,
           ZB_SCHEDULE_ALARM(zb_nwk_mesh_expiry_route_disc, 0, ZB_NWK_EXPIRY_ROUTE_DISCOVERY)));

  /* Check for expired pending entries */
  TRACE_MSG(TRACE_NWK1, "schd pend expiry f %d", (FMT__D,
            ZB_SCHEDULE_ALARM(zb_nwk_mesh_expiry_pending, 0, ZB_NWK_EXPIRY_PENDING)));

  TRACE_MSG(TRACE_NWK1, "<< mesh_r_init", (FMT__0));
}
Пример #2
0
/* This function called periodically to find expired pending elements */
void zb_nwk_mesh_expiry_pending(zb_uint8_t param) 
{
  ZVUNUSED(param);
  TRACE_MSG(TRACE_NWK1, ">> exp_pend", (FMT__0));

  if ( ZG->nwk.nib.pending_table_cnt )
  {
    zb_ushort_t i;

    for (i = 0; i < ZB_NWK_PENDING_TABLE_SIZE; i++)
    {
      if ( ZG->nwk.nib.pending_table[i].used )
      {
        TRACE_MSG(TRACE_NWK1, "pend ent %d dst_addr %d exp %d", (FMT__D_D_D,
                  i, ZG->nwk.nib.pending_table[i].dest_addr, ZG->nwk.nib.pending_table[i].expiry));
        if ( ZG->nwk.nib.pending_table[i].expiry == 0 )
        {
          TRACE_MSG(TRACE_NWK1, "free buf %p", (FMT__P, ZG->nwk.nib.pending_table[i].buf));
          zb_free_buf(ZG->nwk.nib.pending_table[i].buf);
          NWK_ARRAY_PUT_ENT(ZG->nwk.nib.pending_table, &ZG->nwk.nib.pending_table[i], ZG->nwk.nib.pending_table_cnt);
        }
        else
        {
          ZG->nwk.nib.pending_table[i].expiry--;
        }
      }
    }
  }

  /* Schedule to call later */
  ZB_SCHEDULE_ALARM(zb_nwk_mesh_expiry_pending, 0, ZB_NWK_EXPIRY_PENDING);

  TRACE_MSG(TRACE_NWK1, "<< exp_pend", (FMT__0));
}
Пример #3
0
zb_ret_t zb_mlme_orphan_scan() 
{
  zb_ret_t ret = RET_OK;
  zb_mlme_scan_params_t *scan_params;

  /* 7.5.2.1.4
     - discard all frames except realignment command frames
     - switch to the channel
     - send an orphan notification command
     - enable receiver for at most macResponseWaitTime symbols and waits for
     coordinator realignment command
     - if realignment command received - end, otherwise set next channel
  */

  TRACE_MSG(TRACE_MAC1, ">> mlme_orphan_scan", (FMT__0));
  /* clear answer flag */
  scan_params = ZB_GET_BUF_PARAM(MAC_CTX().pending_buf, zb_mlme_scan_params_t);
  MAC_CTX().unscanned_channels = scan_params->channels;

  MAC_CTX().rt_ctx.orphan_scan.got_realignment = 0;

  /* TODO: Configiure transiver to accept only realignment commands */

  ret = ZB_SCHEDULE_ALARM(zb_mlme_scan_step, 0, ZB_MAC_PIB_RESPONSE_WAIT_TIME);

  TRACE_MSG(TRACE_MAC1, "<< mlme_orphan_scan %i", (FMT__D, ret));
  return ret;
}
Пример #4
0
zb_ret_t zb_mlme_ed_scan()
{
  zb_ret_t ret = RET_OK;
  zb_mac_scan_confirm_t *scan_confirm;

/*
  mac spec 7.5.2.1.1 ED channel scan
  - discard all frames received over the PHY data service (UBEC stack accepts only beacon frames)
  - check one-by-one all logical channels, if it is specified in the requested
  channel mask, switch to this channel, set phyCurrentChannel = new_channel_number;
  phyCurrentPage = 0 alwayes for ZB
  - perform ED measurement for current channel during [(aBaseSuperframeDuration * (2^n + 1)) symbols] time.
  - save maximum ED value to confirmation buffer
  - perform scan confirm on procedure finish
*/
  TRACE_MSG(TRACE_MAC1, ">> zb_mlme_ed_scan", (FMT__0));
  {
    zb_mlme_scan_params_t *scan_params = ZB_GET_BUF_PARAM(MAC_CTX().pending_buf, zb_mlme_scan_params_t);
    MAC_CTX().unscanned_channels = scan_params->channels;
    /* timeout is calculated in beacon intervals */
    MAC_CTX().rt_ctx.ed_scan.scan_timeout = (1l << scan_params->scan_duration) + 1;
  }
  ZB_BUF_REUSE(MAC_CTX().pending_buf);
  scan_confirm = ZB_GET_BUF_PARAM(MAC_CTX().pending_buf, zb_mac_scan_confirm_t);
  ZB_ASSERT(scan_confirm);
  ZB_BZERO(scan_confirm, sizeof(zb_mac_scan_confirm_t));
  scan_confirm->unscanned_channels = MAC_CTX().unscanned_channels;

#ifndef ZB_NS_BUILD

  MAC_CTX().rt_ctx.ed_scan.channel_number = ZB_MAC_START_CHANNEL_NUMBER;
  MAC_CTX().rt_ctx.ed_scan.save_channel = MAC_CTX().current_channel;
  MAC_CTX().rt_ctx.ed_scan.max_rssi_value = 0;
  ret = ZB_SCHEDULE_ALARM(zb_mlme_scan_step, 0, MAC_CTX().rt_ctx.ed_scan.scan_timeout);

#else  /* ZB_NS_BUILD */
  ZB_BZERO(&scan_confirm->list.energy_detect[0], sizeof(scan_confirm->list.energy_detect));
  scan_confirm->result_list_size = ZB_MAC_SUPPORTED_CHANNELS;
  ret = ZB_SCHEDULE_CALLBACK(zb_mlme_scan_confirm, ZB_REF_FROM_BUF(MAC_CTX().pending_buf));
#ifdef ZB_CHANNEL_ERROR_TEST
  /* channel interference test, show energy on current channel */
  TRACE_MSG(TRACE_MAC3, "ch_err_test %hd, logical_channel %hd, ch index %hd", (FMT__H_H_H,
                                                                               ZB_MAC_GET_CHANNEL_ERROR_TEST(), ZB_MAC_GET_CURRENT_LOGICAL_CHANNEL(),
                                                                               ZB_MAC_GET_CURRENT_LOGICAL_CHANNEL() - ZB_MAC_START_CHANNEL_NUMBER));

  if (ZB_MAC_GET_CHANNEL_ERROR_TEST())
  {
    scan_confirm->list.energy_detect[ZB_MAC_GET_CURRENT_LOGICAL_CHANNEL() - ZB_MAC_START_CHANNEL_NUMBER] =
      ZB_CHANNEL_BUSY_ED_VALUE + 1;
  }
#endif
#endif /* ZB_NS_BUILD */

  TRACE_MSG(TRACE_MAC1, "<< zb_mlme_ed_scan, ret %i", (FMT__D, ret));
  return ret;
}
Пример #5
0
/* This function called periodically to find expired discovery table entries */
void zb_nwk_mesh_expiry_route_disc(zb_uint8_t param) 
{
  ZVUNUSED(param);
  TRACE_MSG(TRACE_NWK1, ">> exp_r_disc", (FMT__0));

  if ( ZG->nwk.nib.route_disc_table_cnt )
  {
    zb_ushort_t i;

    TRACE_MSG(TRACE_NWK1, "disc tbl ent cnt %d", (FMT__D, ZG->nwk.nib.route_disc_table_cnt));
    for (i = 0; i < ZB_NWK_ROUTE_DISCOVERY_TABLE_SIZE; i++)
    {
      if ( ZG->nwk.nib.route_disc_table[i].used )
      {
        TRACE_MSG(TRACE_NWK1, "ent %d exp_time  %d", (FMT__D_D, i, ZG->nwk.nib.route_disc_table[i].expiration_time));
        if ( ZG->nwk.nib.route_disc_table[i].expiration_time )
        {
          ZG->nwk.nib.route_disc_table[i].expiration_time--;
        }
        else
        {
          zb_nwk_routing_t *route_ent;

          /* free corresponding route record if it's state is not active */
          NWK_ARRAY_FIND_ENT(ZG->nwk.nib.routing_table, route_ent,
                             (route_ent->dest_addr == ZG->nwk.nib.route_disc_table[i].dest_addr)
                             && (route_ent->status != ZB_NWK_ROUTE_STATE_ACTIVE) );

          /* free expired route discovery entry */
          TRACE_MSG(TRACE_NWK1, "free disc ent %d dst_addr %d", (FMT__D_D, i, ZG->nwk.nib.route_disc_table[i].dest_addr));
          NWK_ARRAY_PUT_ENT(ZG->nwk.nib.route_disc_table, &ZG->nwk.nib.route_disc_table[i], ZG->nwk.nib.route_disc_table_cnt);

          if ( route_ent )
          {
            /* report nwk status to the higher layers */
            ZG->nwk.handle.status_ind_addr = route_ent->dest_addr;
            ZB_GET_OUT_BUF_DELAYED(nwk_route_disc_failed);

            TRACE_MSG(TRACE_NWK1, "free routing entrie, addr %d", (FMT__D, route_ent->dest_addr));
            NWK_ARRAY_PUT_ENT(ZG->nwk.nib.routing_table, route_ent, ZG->nwk.nib.routing_table_cnt);
            goto done;
          }
        }
      }
    }
  }

  /* Schedule to call later */
  ZB_SCHEDULE_ALARM(zb_nwk_mesh_expiry_route_disc, 0, ZB_NWK_EXPIRY_ROUTE_DISCOVERY);

  done:
  TRACE_MSG(TRACE_NWK1, "<< exp_r_disc", (FMT__0));
}
Пример #6
0
void zb_zdo_reschedule_poll_parent(zb_uint16_t timeout)
{
  /* reschedule alarm only if we are not waiting for the poll confirm and
   * really need polls */
  if (!(MAC_PIB().mac_rx_on_when_idle
        || ZDO_CTX().inside_poll))
  {
    ZB_SCHEDULE_ALARM_CANCEL(zb_zdo_poll_parent, 0);
    /* If FFD have some pending data for us, we schedule poll w/o timeout */
    ZB_SCHEDULE_ALARM(zb_zdo_poll_parent, 0,  ZB_MAC_GET_PENDING_DATA()? 1 : timeout);
  }
}
Пример #7
0
void nwk_route_disc_failed(zb_uint8_t param) 
{
  zb_nlme_status_indication_t *status =  ZB_GET_BUF_PARAM(ZB_BUF_FROM_REF(param), zb_nlme_status_indication_t);

  TRACE_MSG(TRACE_NWK1, ">> nwk_route_disc_failed", (FMT__0));

  status->status = ZB_NWK_COMMAND_STATUS_NO_ROUTE_AVAILABLE;
  status->network_addr = ZG->nwk.handle.status_ind_addr;

  /* notify */
  ZB_SCHEDULE_CALLBACK(zb_nlme_status_indication, param);
  ZB_SCHEDULE_ALARM_CANCEL(zb_nwk_mesh_expiry_route_disc, 0);
  ZB_SCHEDULE_ALARM(zb_nwk_mesh_expiry_route_disc, 0, ZB_NWK_EXPIRY_ROUTE_DISCOVERY);

  TRACE_MSG(TRACE_NWK1, ">> nwk_route_disc_failed", (FMT__0));
}
Пример #8
0
/* This function called periodically to find expired route requests */
void zb_nwk_mesh_expiry_rreq(zb_uint8_t param) 
{
  TRACE_MSG(TRACE_NWK1, ">> expiry_rreq p %hd", (FMT__H, param));

  TRACE_MSG(TRACE_NWK1, "rreq cnt %d", (FMT__D, ZG->nwk.nib.rreq_cnt));
  if ( ZG->nwk.nib.rreq_cnt )
  {
    zb_ushort_t i = 0;

    for (i = ZG->nwk.nib.rreq_num; i < ZB_NWK_RREQ_TABLE_SIZE; i++)
    {
      if ( ZG->nwk.nib.rreq[i].used )
      {
        /* check we have buffer to send */
        if ( param == (zb_uint8_t)(-1) )
        {
          /* wait for buffer */
          TRACE_MSG(TRACE_NWK1, "wait f/out buf", (FMT__0));
          ZB_GET_OUT_BUF_DELAYED(zb_nwk_mesh_expiry_rreq);
          goto done;
        }

        TRACE_MSG(TRACE_NWK1, "resend %d request", (FMT__D, i));
        zb_nwk_mesh_resend_rreq(ZB_BUF_FROM_REF(param), &ZG->nwk.nib.rreq[i]);
        param = -1;
      }
    }
    ZG->nwk.nib.rreq_num = 0;

    if ( ZG->nwk.nib.rreq_cnt )
    {
      /* Schedule to call later */
      ZB_SCHEDULE_ALARM(zb_nwk_mesh_expiry_rreq, -1, ZB_NWK_RREQ_RETRY_INTERVAL);
    }
  }
  else
  {
    /* No route requests, do not schedule callback */
  }

  done:
  TRACE_MSG(TRACE_NWK1, "<< expiry_rreq", (FMT__0));
}
Пример #9
0
void zb_aps_send_command(zb_uint8_t param, zb_uint16_t dest_addr, zb_uint8_t command, zb_bool_t secure)
{
  zb_buf_t *buf = (zb_buf_t *)ZB_BUF_FROM_REF(param);
  zb_ushort_t need_ack = !ZB_NWK_IS_ADDRESS_BROADCAST(dest_addr);
#ifdef ZB_DISABLE_APS_ACK_REQ
  /* Specially for test with Daintree: do not ask ACK for key transport:
     Daintree wants to encrypt ACK by its predefined key before it receive key from us */
  if (command == APS_CMD_TRANSPORT_KEY)
  {
    need_ack = 0;
  }
#endif
  TRACE_MSG(TRACE_SECUR3, ">>zb_aps_send_command param %hd cmd %hd secur %hd to %d need_ack %hd", (FMT__H_H_H_D_H, param, command, secure, dest_addr, need_ack));

  if (need_ack)
  {
    zb_uint8_t i;
    for (i = 0 ; i < ZB_N_APS_RETRANS_ENTRIES ; ++i)
    {
      if (ZG->aps.retrans.hash[i].state == ZB_APS_RETRANS_ENT_FREE)
      {
        ZG->aps.retrans.hash[i].addr = dest_addr;
        ZG->aps.retrans.hash[i].aps_counter = ZB_AIB_APS_COUNTER();
        ZG->aps.retrans.hash[i].buf = param;
        ZG->aps.retrans.hash[i].nwk_insecure = !secure;
        ZG->aps.retrans.hash[i].aps_retries = ZB_N_APS_MAX_FRAME_ENTRIES;
        ZG->aps.retrans.hash[i].state = ZB_APS_RETRANS_ENT_SENT_MAC_NOT_CONFIRMED_ALRM_RUNNING;
        TRACE_MSG(TRACE_APS2, "Store buf %hd len %hd in retrans hash %d", (FMT__H_H, param, ZB_BUF_LEN(buf), i));

        DUMP_TRAF("sending aps cmd", ZB_BUF_BEGIN(buf), ZB_BUF_LEN(buf));

        break;
      }
    }
    if (i == ZB_N_APS_RETRANS_ENTRIES)
    {
      TRACE_MSG(TRACE_APS2, "ACK table is FULL", (FMT__0));
    }
    else
    {
      ZB_SCHEDULE_ALARM(zb_aps_ack_timer_cb, i, ZB_N_APS_ACK_WAIT_DURATION);
    }
  }

  /* Fill APS command header - see 2.2.5.2.2  APS Command Frame Format.
     At the same time alloc and fill aux security header
   */

  {
    zb_aps_command_header_t *hdr;

#ifdef ZB_SECURITY
#ifdef APS_FRAME_SECURITY
    buf->u.hdr.encrypt_type = ZB_SECUR_NO_ENCR;
    if (secure)
    {
      /* Allocate here space for APS command header, aux header and command id
       * (it is in payload). */
      secure = zb_aps_command_add_secur(buf, command);
      hdr = (zb_aps_command_header_t *)ZB_BUF_BEGIN(buf);
    }
    else
#endif
#endif
    {
      /* no security - just aps command header */
      ZB_BUF_ALLOC_LEFT(buf, sizeof (*hdr), hdr);
      hdr->fc = 0;
      hdr->aps_command_id = command;
    }

    ZB_APS_FC_SET_COMMAND(hdr->fc, need_ack);
    hdr->aps_counter = ZB_AIB_APS_COUNTER();
  }
  ZB_AIB_APS_COUNTER_INC();

  fill_nldereq(param, dest_addr, secure);
  TRACE_MSG(TRACE_SECUR3, "send APS cmd %hd secur %hd to %d", (FMT__H_H_D, command, secure, dest_addr));

  ZB_SCHEDULE_CALLBACK(zb_nlde_data_request, param);
}
Пример #10
0
/*
 * Generate and send a route request command frame.
 * Add route request entry into the rreq list to be able to track this request.
*/
static zb_ret_t zb_nwk_mesh_send_rreq(zb_buf_t *cbuf, zb_nwk_cmd_rreq_t *nwk_cmd_rreq, zb_uint16_t src_addr, zb_uint8_t seq_num, zb_uint8_t path_cost, zb_uint8_t radius) 
{
  zb_ret_t ret = RET_OK;

  TRACE_MSG(TRACE_NWK1, ">> send_rreq cbuf %p rreq %p s_addr %d path_cost %hd radius %hd", (FMT__P_P_D_H_H,
                         cbuf, nwk_cmd_rreq, src_addr, path_cost, radius));

#if 0
  /* check we have room in rreq table */
  if ( ZG->nwk.nib.rreq_cnt < ZB_NWK_RREQ_TABLE_SIZE )
#endif
  {
    zb_nwk_hdr_t *nwhdr;
    zb_nwk_cmd_rreq_t *rreq_cmd;
#if 0
    zb_nwk_rreq_t *rreq;
#endif
    zb_bool_t secure = ZB_FALSE;

#ifdef ZB_SECURITY
    secure = (ZG->aps.authenticated && ZG->nwk.nib.secure_all_frames
             && ZG->nwk.nib.security_level);
#endif

    nwhdr = nwk_alloc_and_fill_hdr(cbuf,
                                   ZB_NWK_BROADCAST_ROUTER_COORDINATOR, NULL, NULL, ZB_FALSE, secure, ZB_TRUE);
    rreq_cmd = (zb_nwk_cmd_rreq_t *)nwk_alloc_and_fill_cmd(cbuf, ZB_NWK_CMD_ROUTE_REQUEST, sizeof(zb_nwk_cmd_rreq_t));
    rreq_cmd->opt = 0;
    rreq_cmd->rreq_id = nwk_cmd_rreq->rreq_id;
    rreq_cmd->dest_addr = nwk_cmd_rreq->dest_addr;
    ZB_NWK_ADDR_TO_LE16(rreq_cmd->dest_addr);
    rreq_cmd->path_cost = path_cost;
    nwhdr->radius = radius;
    nwhdr->src_addr = src_addr;

    /* Not sure it is right, but let's assign original seq_num. Else request
     * can be dropped as a dup at receiver's side. */
    if (src_addr != ZB_NIB_NETWORK_ADDRESS())
    {
      nwhdr->seq_num = seq_num;
    }

#if 0
    /* Save info to retransmit request ZB_MWK_RREQ_RETRIES times */
    NWK_ROUTING_ARRAY_GET_ENT(ZG->nwk.nib.rreq, rreq, ZG->nwk.nib.rreq_cnt);
    ZB_ASSERT(rreq);
    if ( rreq )
    {
      rreq->originator = src_addr;
      rreq->radius = radius;
      rreq->retries = 1;
      memcpy(&rreq->cmd, rreq_cmd, sizeof(rreq->cmd));

      /* schedule resend function */
      if ( ZG->nwk.nib.rreq_cnt == 1 )
      {
        ZB_SCHEDULE_ALARM_CANCEL(zb_nwk_mesh_expiry_rreq, ZB_ALARM_ANY_PARAM);
        ZB_SCHEDULE_ALARM(zb_nwk_mesh_expiry_rreq, -1, ZB_NWK_RREQ_RETRY_INTERVAL);
      }
    }
#endif

    /* transmit route request packet */
    ZB_SET_BUF_PARAM(cbuf, ZB_NWK_INTERNAL_NSDU_HANDLE, zb_uint8_t);
    ZB_SCHEDULE_CALLBACK(zb_nwk_forward, ZB_REF_FROM_BUF(cbuf));
  }
#if 0
  else
  {
    zb_free_buf(cbuf);
    TRACE_MSG(TRACE_NWK1, "rreq buffer is full", (FMT__0));
    ret = RET_NO_MEMORY;
  }
#endif

  TRACE_MSG(TRACE_NWK1, "<< send_rreq %d", (FMT__D, ret));
  return ret;
}
Пример #11
0
/* this is a universal routine for ed/active/orphan scans */
void zb_mlme_scan_step(zb_uint8_t param) 
{
  zb_uint8_t channel_number;
  zb_mlme_scan_params_t *scan_params;
  zb_ret_t ret = RET_OK;
  zb_uint16_t timeout;
  zb_uint32_t *unscanned_channels;

  TRACE_MSG(TRACE_MAC1, ">> zb_mlme_scan_step", (FMT__0));
  ZVUNUSED(param);
  channel_number = ZB_MAC_START_CHANNEL_NUMBER;
  scan_params = ZB_GET_BUF_PARAM(MAC_CTX().pending_buf, zb_mlme_scan_params_t);
  /* Table 2.80   Fields of the Mgmt_NWK_Disc_req Command (the other scans
     requests are using the same parameters
     A value used to calculate the length
     of time to spend scanning each
     channel. The time spent scanning
     each channel is
     (aBaseSuperframeDuration * (2^n +
     1)) symbols, where n is the value of
     the ScanDuration parameter. */
  timeout = (1l << scan_params->scan_duration) + 1;
  MAC_CTX().mlme_scan_in_progress = 1;
  unscanned_channels = &MAC_CTX().unscanned_channels;
  for (;channel_number < ZB_MAC_START_CHANNEL_NUMBER + ZB_MAC_MAX_CHANNEL_NUMBER;channel_number++)
  {
    if (*unscanned_channels & 1l<<channel_number)
    {
      TRACE_MSG(TRACE_MAC2, "set channel %hd", (FMT__H, channel_number));
      ZB_TRANSCEIVER_SET_CHANNEL(channel_number);
      *unscanned_channels &=~(1l<<channel_number);
      if (scan_params->scan_type == ACTIVE_SCAN)
      {
        ret = zb_beacon_request_command();
        if (ret == RET_OK)
        {
          /* check beacon request TX status */
          /* There's nothing to do during active scan, so, synchronous */
          ret = zb_check_cmd_tx_status();
        }
      }
      
      ZB_SCHEDULE_ALARM_CANCEL(zb_mlme_scan_step, 0);
      ret = ZB_SCHEDULE_ALARM(zb_mlme_scan_step, 0, timeout);
      break;
    }
  }
  if (channel_number == (ZB_MAC_START_CHANNEL_NUMBER + ZB_MAC_MAX_CHANNEL_NUMBER))
  {
    zb_mac_scan_confirm_t *scan_confirm;
    /* There's no need to restore channel
       after active or orphan scan, because we will choose
       new channel, according to scan results.
    */
    /* ZB_TRANSCEIVER_SET_CHANNEL(MAC_CTX().rt_ctx.ed_scan.save_channel);*/
    scan_confirm = ZB_GET_BUF_PARAM(MAC_CTX().pending_buf, zb_mac_scan_confirm_t);
    TRACE_MSG(TRACE_MAC3, "beacon found %hd", (FMT__H, MAC_CTX().rt_ctx.active_scan.beacon_found));
    if (scan_params->scan_type == ED_SCAN || MAC_CTX().rt_ctx.active_scan.beacon_found
        || MAC_CTX().rt_ctx.orphan_scan.got_realignment)
    {
      scan_confirm->status = MAC_SUCCESS;
      /* Q: do we really need to zero here?  What about got_realignment?
       *
       * A: I think yes, because it is the only indication
       * for NO_BEACON status, that will not affect ED or ORPHAN scans. ED just
       * doesn't need any packets, and ORPHAN needs a realignment command that
       * is processed in appropriate function */
      MAC_CTX().rt_ctx.active_scan.beacon_found = 0;
    }
    else
    {
      scan_confirm->status = MAC_NO_BEACON;
    }
#ifdef ZB_MAC_TESTING_MODE
    {
      scan_confirm->result_list_size = desc_count;
    }
#endif
    scan_confirm->scan_type = scan_params->scan_type;
    MAC_CTX().mlme_scan_in_progress = 0;
    ZB_SCHEDULE_CALLBACK(zb_mlme_scan_confirm, ZB_REF_FROM_BUF(MAC_CTX().pending_buf));
  }
  TRACE_MSG(TRACE_MAC1, "<< zb_mlme_scan_step", (FMT__0));
}