static void linkTo()
{
  uint8_t     msg[2];
  uint8_t     button, misses, done;

  /* Keep trying to link... */
  while (SMPL_SUCCESS != SMPL_Link(&sLinkID1))
  {
    toggleLED(1);
    toggleLED(2);
    SPIN_ABOUT_A_SECOND;
  }

  /* Turn off LEDs. */
  if (BSP_LED2_IS_ON())
  {
    toggleLED(2);
  }
  if (BSP_LED1_IS_ON())
  {
    toggleLED(1);
  }

  /* sleep until button press... */
  SMPL_Ioctl( IOCTL_OBJ_RADIO, IOCTL_ACT_RADIO_SLEEP, 0);

  while (1)
  {
    button = 0;
    /* Send a message when either button pressed */
    if (BSP_BUTTON1())
    {
      SPIN_ABOUT_A_QUARTER_SECOND;  /* debounce... */
      /* Message to toggle LED 1. */
      button = 1;
    }
    else if (BSP_BUTTON2())
    {
      SPIN_ABOUT_A_QUARTER_SECOND;  /* debounce... */
      /* Message to toggle LED 2. */
      button = 2;
    }
    if (button)
    {
      uint8_t      noAck;
      smplStatus_t rc;

      /* get radio ready...awakens in idle state */
      SMPL_Ioctl( IOCTL_OBJ_RADIO, IOCTL_ACT_RADIO_AWAKE, 0);

      /* Set TID and designate which LED to toggle */
      msg[1] = ++sTid;
      msg[0] = (button == 1) ? 1 : 2;
      done = 0;
      while (!done)
      {
        noAck = 0;

        /* Try sending message MISSES_IN_A_ROW times looking for ack */
        for (misses=0; misses < MISSES_IN_A_ROW; ++misses)
        {
          if (SMPL_SUCCESS == (rc=SMPL_SendOpt(sLinkID1, msg, sizeof(msg), SMPL_TXOPTION_ACKREQ)))
          {
            /* Message acked. We're done. Toggle LED 1 to indicate ack received. */
            toggleLED(1);
            break;
          }
          if (SMPL_NO_ACK == rc)
          {
            /* Count ack failures. Could also fail becuase of CCA and
             * we don't want to scan in this case.
             */
            noAck++;
          }
        }
        if (MISSES_IN_A_ROW == noAck)
        {
          /* Message not acked. Toggle LED 2. */
          toggleLED(2);
#ifdef FREQUENCY_AGILITY
          /* Assume we're on the wrong channel so look for channel by
           * using the Ping to initiate a scan when it gets no reply. With
           * a successful ping try sending the message again. Otherwise,
           * for any error we get we will wait until the next button
           * press to try again.
           */
          if (SMPL_SUCCESS != SMPL_Ping(sLinkID1))
          {
            done = 1;
          }
#else
          done = 1;
#endif  /* FREQUENCY_AGILITY */
        }
        else
        {
          /* Got the ack or we don't care. We're done. */
          done = 1;
        }
      }

      /* radio back to sleep */
      SMPL_Ioctl( IOCTL_OBJ_RADIO, IOCTL_ACT_RADIO_SLEEP, 0);
    }
  }
}
//*****************************************************************************
//
// Link to the access point and continue processing local button requests
// forever.  This function is called following initialization in main() and
// does not return.
//
//*****************************************************************************
static void
LinkTo(void)
{
    uint8_t     pucMsg[2];
    uint8_t     ucMisses, ucDone;
    uint8_t     ucNoAck;
    smplStatus_t eRetcode;
    unsigned long ulButton;

    UpdateStatus(false, "Linking to Access Point");

    //
    // Keep trying to link.  Flash our "LEDs" while these attempts continue.
    //
    while (SMPL_SUCCESS != SMPL_Link(&g_sLinkID))
    {
        ToggleLED(1);
        ToggleLED(2);
        SPIN_ABOUT_A_SECOND;
    }

    //
    // Turn off both LEDs now that we are linked.
    //
    SetLED(1, false);
    SetLED(2, false);

    //
    // Tell the user all is well.
    //
    UpdateStatus(false, "Link successful");

    //
    // Put the radio to sleep until a button is pressed.
    //
    SMPL_Ioctl( IOCTL_OBJ_RADIO, IOCTL_ACT_RADIO_SLEEP, 0);

    //
    // Start of the main button processing loop.
    //
    while (1)
    {

        //
        // Grab the button press flag and clear it.  We do this since the flag
        // could be changed during the loop whenever function
        // WidgetMessageQueueProcess() is called and we don't want to miss any
        // button presses.
        //
        ulButton = g_ulButtonPressed;

        //
        // Has either button been pressed?
        //
        if (ulButton)
        {
            //
            // Clear the main button press flag.
            //
            g_ulButtonPressed = 0;

            //
            // Wake the radio up since we are about to need it.
            //
            SMPL_Ioctl( IOCTL_OBJ_RADIO, IOCTL_ACT_RADIO_AWAKE, 0);

            /* Set TID and designate which LED to toggle */
            pucMsg[1] = ++g_ucTid;
            pucMsg[0] = (ulButton == 1) ? 1 : 2;
            ucDone = 0;
            while (!ucDone)
            {

                //
                // Remember that we have yet to receive an ack from the AP.
                //
                ucNoAck = 0;

                //
                // Try sending the message MISSES_IN_A_ROW times looking for an
                // ack after each transmission.
                //
                for (ucMisses = 0; ucMisses < MISSES_IN_A_ROW; ucMisses++)
                {
                    //
                    // Send the message and request acknowledgement.
                    //
                    eRetcode=SMPL_SendOpt(g_sLinkID, pucMsg, sizeof(pucMsg),
                                          SMPL_TXOPTION_ACKREQ);

                    //
                    // Did we get the ack?
                    //
                    if (eRetcode == SMPL_SUCCESS)
                    {
                        //
                        // Yes - Message acked.  We're done.  Toggle LED 1 to
                        // indicate ack received. */
                        ToggleLED(1);
                        break;
                    }

                    //
                    // Did we send the message but fail to get an ack back?
                    //
                    if (SMPL_NO_ACK == eRetcode)
                    {
                        //
                        // Count ack failures.  Could also fail because of CCA
                        // and we don't want to scan in this case.
                        //
                        ucNoAck++;
                    }
                }

                //
                // Did we fail to get an ack after every transmission?
                //
                if (MISSES_IN_A_ROW == ucNoAck)
                {
                    //
                    // Tell the user what happened.
                    //
                    UpdateStatus(false, "Channel changed?");

                    //
                    // Message not acked.  Toggle LED 2.
                    //
                    ToggleLED(2);

#ifdef FREQUENCY_AGILITY
                    //
                    // At this point, we assume we're on the wrong channel so
                    // look for the correct channel by using Ping to initiate a
                    // scan when it gets no reply.  With a successful ping try
                    // sending the message again.  Otherwise, for any error we
                    // get we will wait until the next button press to try
                    // again.
                    //
                    if (SMPL_SUCCESS != SMPL_Ping(g_sLinkID))
                    {
                        ucDone = 1;
                    }
#else
                    ucDone = 1;
#endif  /* FREQUENCY_AGILITY */
                }
                else
                {
                    //
                    // We got the ack so drop out of the transmit loop.
                    //
                    ucDone = 1;

                    UpdateStatus(false, "Toggled AP LED %d", ulButton);
                }
            }

            //
            // Now that we are finished with it, put the radio back to sleep.
            //
            SMPL_Ioctl( IOCTL_OBJ_RADIO, IOCTL_ACT_RADIO_SLEEP, 0);
        }

        //
        // Process the widget message queue.
        //
        WidgetMessageQueueProcess();
    }
}