Exemplo n.º 1
0
/*
 * @brief Checks for matching short address
 *
 * This callback function checks whether the passed short address
 * matches with the frame in the queue.
 *
 * @param buf Pointer to indirect data buffer
 * @param short_addr Short address to be searched
 *
 * @return 1 if short address passed matches with the destination
 * address of the indirect frame , 0 otherwise
 */
static uint8_t find_short_buffer(void *buf, void *short_addr)
{
    frame_info_t *data = (frame_info_t *)buf;

    if (!data->indirect_in_transit)
    {
        /*
         * Read octet 2 of Frame Control Field containing the type
         * of destination address.
         */
        uint8_t dst_addr_mode = (data->mpdu[PL_POS_FCF_2] >> FCF_2_DEST_ADDR_OFFSET) & FCF_ADDR_MASK;

        /*
         * Compare indirect data frame's dest_address(short)
         * with short address passed.
         */
        if ((dst_addr_mode == FCF_SHORT_ADDR) &&
            (*(uint16_t *)short_addr == convert_byte_array_to_16_bit(&data->mpdu[PL_POS_DST_ADDR_START]))
           )
        {
            return 1;
        }
    }
Exemplo n.º 2
0
/**
 * @brief Processes received beacon frame
 *
 * This function processes a received beacon frame.
 * When the system is scanning it records PAN descriptor information
 * contained in the beacon. These PAN descriptors will be reported to the
 * next higher layer via MLME_SCAN.confirm.
 * Also this routine constructs the MLME_BEACON_NOTIFY.indication.
 * Additionally when a device is synced with the coordinator, it tracks beacon
 * frames, checks whether the coordinator does have pending data and will
 * initiate the transmission of a data request frame.
 * The routine uses global "parse_data" structure.
 * The PAN descriptors are stored in the mlme_scan_conf_t structure.
 *
 * @param beacon Pointer to the buffer in which the beacon was received
 *
 */
void mac_process_beacon_frame(buffer_t *beacon)
{
    bool matchflag;
    wpan_pandescriptor_t *pand_long_start_p = NULL;
    wpan_pandescriptor_t pand_long;
    mlme_scan_conf_t *msc = NULL;

#if ((MAC_BEACON_NOTIFY_INDICATION == 1) || \
     ((MAC_INDIRECT_DATA_BASIC == 1) && (MAC_SYNC_REQUEST == 1)) \
    )
    uint8_t numaddrshort;
    uint8_t numaddrlong;
#endif

#ifdef BEACON_SUPPORT
    uint16_t beacon_length;

    /*
     * Extract the superframe parameters of the beacon frame only if
     * scanning is NOT ongoing.
     */
    if (MAC_SCAN_IDLE == mac_scan_state)
    {
#if (MAC_START_REQUEST_CONFIRM == 1)
        /* Beacon frames are not of interest for a PAN coordinator. */
        if (MAC_PAN_COORD_STARTED != mac_state)
#endif /* MAC_START_REQUEST_CONFIRM */
        {
            uint8_t superframe_order;
            uint8_t beacon_order;

            /*
             * For a device, the parameters obtained from the beacons are used to
             * update the PIBs at TAL
             */
            beacon_order =
                GET_BEACON_ORDER(mac_parse_data.mac_payload_data.beacon_data.superframe_spec);

#if (_DEBUG_ > 0)
            retval_t set_status =
#endif
            set_tal_pib_internal(macBeaconOrder, (void *)&beacon_order);

#if (_DEBUG_ > 0)
            Assert(MAC_SUCCESS == set_status);
#endif
            superframe_order =
                GET_SUPERFRAME_ORDER(mac_parse_data.mac_payload_data.beacon_data.superframe_spec);
#if (_DEBUG_ > 0)
            set_status =
#endif
            set_tal_pib_internal(macSuperframeOrder, (void *)&superframe_order);

#if (_DEBUG_ > 0)
            Assert(MAC_SUCCESS == set_status);
#endif

            mac_final_cap_slot =
            GET_FINAL_CAP(mac_parse_data.mac_payload_data.beacon_data.superframe_spec);

            /*
             * In a beacon-enabled network with the batterylife extension
             * enabled, the first backoff slot boundary is computed after the
             * end of the beacon's IFS
             */
            if ((tal_pib.BeaconOrder < NON_BEACON_NWK) && tal_pib.BattLifeExt)
            {
                /* Length given in octets */
                beacon_length = mac_parse_data.mpdu_length + PHY_OVERHEAD;

                /* Convert to symbols */
                beacon_length *= SYMBOLS_PER_OCTET;

                /* Space needed for IFS is added to it */
                if (mac_parse_data.mpdu_length <= aMaxSIFSFrameSize)
                {
                    beacon_length += macMinSIFSPeriod_def;
                }
                else
                {
                    beacon_length += macMinLIFSPeriod_def;
                }

                /* Round up to backoff slot boundary */
                beacon_length = (beacon_length + aUnitBackoffPeriod - 1) / aUnitBackoffPeriod;
                beacon_length *= aUnitBackoffPeriod;

                /*
                 * Slotted CSMA-CA with macBattLifeExt must start within
                 * the first macBattLifeExtPeriods backoff slots of the CAP
                 */
                beacon_length += mac_pib.mac_BattLifeExtPeriods * aUnitBackoffPeriod;
            }
        }   /* (MAC_PAN_COORD_STARTED != mac_state) */
    }   /* (MAC_SCAN_IDLE == mac_scan_state) */
#endif  /* BEACON_SUPPORT */

    /*
     * The following section needs to be done when we are
     * either scanning (and look for a new PAN descriptor to be returned
     * as part of the scan confirm message),
     * or we need to create a beacon notification (in which case we are
     * interested in any beacon, but omit the generation of scan confirm).
     */
    {
        uint8_t index;

        /*
         * If we are scanning a scan confirm needs to be created.
         *
         * According to 802.15.4-2006 this is only done in case the PIB
         * attribute macAutoRequest is true. Otherwise the PAN descriptor will
         * NOT be put into the PAN descriptor list of the Scan confirm message.
         */
        if (
            ((MAC_SCAN_ACTIVE == mac_scan_state) || (MAC_SCAN_PASSIVE == mac_scan_state)) &&
            mac_pib.mac_AutoRequest
           )
        {
            /*
             * mac_conf_buf_ptr points to the buffer allocated for scan
             * confirmation.
             */
             msc =  (mlme_scan_conf_t *)BMM_BUFFER_POINTER(
                        ((buffer_t *)mac_conf_buf_ptr));

            /*
             * The PAN descriptor list is updated with the PANDescriptor of the
             * received beacon
             */
            pand_long_start_p = (wpan_pandescriptor_t *)&msc->scan_result_list;
        }

        /*
         * The beacon data received from the parse variable is arranged
         * into a PAN descriptor structure style
         */
        pand_long.CoordAddrSpec.AddrMode = mac_parse_data.src_addr_mode;
        pand_long.CoordAddrSpec.PANId = mac_parse_data.src_panid;

        if (FCF_SHORT_ADDR == pand_long.CoordAddrSpec.AddrMode)
        {
            /* Initially clear the complete address. */
            pand_long.CoordAddrSpec.Addr.long_address = 0;

            ADDR_COPY_DST_SRC_16(pand_long.CoordAddrSpec.Addr.short_address, mac_parse_data.src_addr.short_address);
        }
        else
        {
            ADDR_COPY_DST_SRC_64(pand_long.CoordAddrSpec.Addr.long_address, mac_parse_data.src_addr.long_address);
        }

        pand_long.LogicalChannel = tal_pib.CurrentChannel;
        pand_long.ChannelPage    = tal_pib.CurrentPage;
        pand_long.SuperframeSpec = mac_parse_data.mac_payload_data.beacon_data.superframe_spec;
        pand_long.GTSPermit      = mac_parse_data.mac_payload_data.beacon_data.gts_spec >> 7;
        pand_long.LinkQuality    = mac_parse_data.ppdu_link_quality;
#ifdef ENABLE_TSTAMP
        pand_long.TimeStamp      = mac_parse_data.time_stamp;
#endif  /* ENABLE_TSTAMP */

        /*
         * If we are scanning we need to check whether this is a new
         * PAN descriptor.
         *
         * According to 802.15.4-2006 this is only done in case the PIB
         * attribute macAutoRequest is true. Otherwise the PAN descriptor will
         * NOT be put into the PAN descriptor list of the Scan confirm message.
         */
        if (
            ((MAC_SCAN_ACTIVE == mac_scan_state) || (MAC_SCAN_PASSIVE == mac_scan_state)) &&
            mac_pib.mac_AutoRequest
           )
        {
            /*
             * This flag is used to indicate a match of the current (received) PAN
             * descriptor with one of those present already in the list.
             */
            matchflag = false;

            /*
             * The beacon frame PAN descriptor is compared with the PAN descriptors
             * present in the list and determine if the current PAN
             * descriptor is to be taken as a valid one. A PAN is considered to be
             * the same as an existing one, if all, the PAN Id, the coordinator address
             * mode, the coordinator address, and the Logical Channel are same.
             */
            for (index = 0; index < msc->ResultListSize; index++, pand_long_start_p++)
            {
                if ((pand_long.CoordAddrSpec.PANId == pand_long_start_p->CoordAddrSpec.PANId) &&
                    (pand_long.CoordAddrSpec.AddrMode == pand_long_start_p->CoordAddrSpec.AddrMode) &&
                    (pand_long.LogicalChannel == pand_long_start_p->LogicalChannel) &&
                    (pand_long.ChannelPage == pand_long_start_p->ChannelPage)
                   )
                {
                    if (pand_long.CoordAddrSpec.AddrMode == WPAN_ADDRMODE_SHORT)
                    {
                        if (pand_long.CoordAddrSpec.Addr.short_address == pand_long_start_p->CoordAddrSpec.Addr.short_address)
                        {
                            /* Beacon with same parameters already received */
                            matchflag = true;
                            break;
                        }
                    }
                    else
                    {
                        if (pand_long.CoordAddrSpec.Addr.long_address == pand_long_start_p->CoordAddrSpec.Addr.long_address)
                        {
                            /* Beacon with same parameters already received */
                            matchflag = true;
                            break;
                        }
                    }
                }
            }

            /*
             * If the PAN descriptor is not in the current list, and there is space
             * left, it is put into the list
             */
            if ((!matchflag) && (msc->ResultListSize < MAX_PANDESCRIPTORS))
            {
                memcpy(pand_long_start_p, &pand_long, sizeof(pand_long));
                msc->ResultListSize++;
            }
        }
    }


#if ((MAC_BEACON_NOTIFY_INDICATION == 1) || \
     ((MAC_INDIRECT_DATA_BASIC == 1) && (MAC_SYNC_REQUEST == 1)) \
    )
    /* The short and extended pending addresses are extracted from the beacon */
    numaddrshort =
        NUM_SHORT_PEND_ADDR(mac_parse_data.mac_payload_data.beacon_data.pending_addr_spec);

    numaddrlong =
        NUM_LONG_PEND_ADDR(mac_parse_data.mac_payload_data.beacon_data.pending_addr_spec);
#endif

#if (MAC_BEACON_NOTIFY_INDICATION == 1)
    /*
     * In all cases (PAN or device) if the payload is not equal to zero
     * or macAutoRequest is false, MLME_BEACON_NOTIFY.indication is
     * generated
     */
    if ((mac_parse_data.mac_payload_data.beacon_data.beacon_payload_len > 0) ||
        (!mac_pib.mac_AutoRequest)
       )
    {
        mlme_beacon_notify_ind_t *mbni =
            (mlme_beacon_notify_ind_t *)BMM_BUFFER_POINTER(((buffer_t *)beacon));

        /* The beacon notify indication structure is built */
        mbni->cmdcode       = MLME_BEACON_NOTIFY_INDICATION;
        mbni->BSN           = mac_parse_data.sequence_number;
        mbni->PANDescriptor = pand_long;
        mbni->PendAddrSpec  = mac_parse_data.mac_payload_data.beacon_data.pending_addr_spec;

        if ((numaddrshort > 0) || (numaddrlong > 0))
        {
            mbni->AddrList = mac_parse_data.mac_payload_data.beacon_data.pending_addr_list;
        }

        mbni->sduLength = mac_parse_data.mac_payload_data.beacon_data.beacon_payload_len;
        mbni->sdu = mac_parse_data.mac_payload_data.beacon_data.beacon_payload;

        /*
         * The beacon notify indication is given to the NHLE and then the buffer
         * is freed up.
         */
        qmm_queue_append(&mac_nhle_q, (buffer_t *)beacon);
    }
    else
#endif /* (MAC_BEACON_NOTIFY_INDICATION == 1) */
    {
        /* Payload is not present, hence the buffer is freed here */
        bmm_buffer_free(beacon);
    }


/* Handling of ancounced broadcast traffic by the parent. */
#ifdef BEACON_SUPPORT
    if (MAC_SCAN_IDLE == mac_scan_state)
    {
        /*
         * In case this is a beaconing network, and this node is not scanning,
         * and the FCF indicates pending data thus indicating broadcast data at
         * parent, the node needs to be awake until the received broadcast
         * data has been received.
         */
        if (mac_parse_data.fcf & FCF_FRAME_PENDING)
        {
            mac_bc_data_indicated = true;

            /*
             * Start timer since the broadcast frame is expected within
             * macMaxFrameTotalWaitTime symbols.
             */
            if (MAC_POLL_IDLE == mac_poll_state)
            {
                /*
                 * If the poll state is not idle, there is already an
                 * indirect transaction ongoing.
                 * Since the T_Poll_Wait_Time is going to be re-used,
                 * this timer can only be started, if we are not in
                 * a polling state other than idle.
                 */
                uint32_t response_timer = mac_pib.mac_MaxFrameTotalWaitTime;
                response_timer = TAL_CONVERT_SYMBOLS_TO_US(response_timer);

                if (MAC_SUCCESS != pal_timer_start(T_Poll_Wait_Time,
                                                   response_timer,
                                                   TIMEOUT_RELATIVE,
                                                   (FUNC_PTR)mac_t_wait_for_bc_time_cb,
                                                   NULL))
                {
                    mac_t_wait_for_bc_time_cb(NULL);
                }
            }
            else
            {
                /*
                 * Any indirect poll operation is ongoing, so the timer will
                 * not be started, i.e. nothing to be done here.
                 * Once this ongoing indirect transaction has finished, this
                 * node will go back to sleep anyway.
                 */
            }
        }
        else
        {
            mac_bc_data_indicated = false;
        }

    }   /* (MAC_SCAN_IDLE == mac_scan_state) */
#endif /* BEACON_SUPPORT */


/* Handling of presented indirect traffic by the parent for this node. */
#if ((MAC_INDIRECT_DATA_BASIC == 1) && (MAC_SYNC_REQUEST == 1))
    if (MAC_SCAN_IDLE == mac_scan_state)
    {
        /*
         * If this node is NOT scanning, and is doing a mlme_sync_request,
         * then the pending address list of the beacon is examined to see
         * if the node's parent has data for this node.
         */
        if (mac_pib.mac_AutoRequest)
        {
            if (MAC_SYNC_NEVER != mac_sync_state)
            {
                uint8_t index;
#if (_DEBUG_ > 0)
                bool status;
#endif
                /*
                 * Short address of the device is compared with the
                 * pending short address in the beacon frame
                 */

                /*
                 * PAN-ID and CoordAddress does not have to be checked here,
                 * since the device is already synced with the coordinator, and
                 * only beacon frames passed from data_ind.c (where the first level
                 * filtering is already done) are received. The pending addresses
                 * in the beacon frame are compared with the device address. If a
                 * match is found, it indicates that a data belonging to this
                 * deivce is present with the coordinator and hence a data request
                 * is sent to the coordinator.
                 */
                uint16_t cur_short_addr;

                for (index = 0; index < numaddrshort; index++)
                {
                    cur_short_addr = convert_byte_array_to_16_bit((mac_parse_data.mac_payload_data.beacon_data.pending_addr_list +
                                                    index * sizeof(uint16_t)));
                    if (cur_short_addr == tal_pib.ShortAddress)
                    {
                        /*
                         * Device short address matches with one of the address
                         * in the beacon address list. Implicit poll (using the
                         * device short address) is done to get the pending data
                         */
#if (_DEBUG_ > 0)
                        status =
#endif
                            mac_build_and_tx_data_req(false, false, 0, NULL, 0);

#if (_DEBUG_ > 0)
                        Assert(status == true);
#endif
                        return;
                    }
                }

                /*
                 * Extended address of the device is compared with
                 * the pending extended address in the beacon frame
                 */
                uint64_t cur_long_addr;

                for (index = 0; index < numaddrlong; index++)
                {
                    cur_long_addr = convert_byte_array_to_64_bit((mac_parse_data.mac_payload_data.beacon_data.pending_addr_list +
                                                    numaddrshort * sizeof(uint16_t) + index * sizeof(uint64_t)));

                    if (cur_long_addr == tal_pib.IeeeAddress)
                    {
                        /*
                         * Device extended address matches with one of the
                         * address in the beacon address list. Implicit poll
                         * (using the device extended address) is done to get
                         * the pending data
                         */
#if (_DEBUG_ > 0)
                        status =
#endif
                            mac_build_and_tx_data_req(false, true, 0, NULL, 0);


#if (_DEBUG_ > 0)
                        Assert(status == true);
#endif
                        return;
                    }
                }
            }
        }   /* (mac_pib.mac_AutoRequest) */
    }   /* (MAC_SCAN_IDLE == mac_scan_state) */
#endif /* (MAC_INDIRECT_DATA_BASIC == 1) && (MAC_SYNC_REQUEST == 1)) */
} /* mac_process_beacon_frame() */
Exemplo n.º 3
0
/**
 * @brief Processes a received data request command frame
 *
 * This function processes a received data request command frame
 * at the coordinator, searches for pending indirect data frames
 * for the originator and initiates the frame transmission of the
 * data frame with CSMA-CA.
 *
 * @param msg Frame reception buffer pointer
 */
void mac_process_data_request(buffer_t *msg)
{
    /* Buffer pointer to next indirect data frame to be transmitted. */
    buffer_t *buf_ptr_next_data;
    search_t find_buf;
    frame_info_t *transmit_frame;
    retval_t tal_tx_status;

    /* Free the buffer of the received frame. */
    bmm_buffer_free(msg);

    /* Ignore data request if we are not PAN coordinator or coordinator. */
    if ((MAC_IDLE == mac_state) ||
        (MAC_ASSOCIATED == mac_state)
       )
    {
#if (DEBUG > 0)
        ASSERT("Neither PAN coordinator nor coordinator" == 0);
#endif
        return;
    }

    /* Check the addressing mode */
    if (mac_parse_data.src_addr_mode == FCF_SHORT_ADDR)
    {
        /*
         * Look for pending data in the indirect queue for
         * this short address.
         */

        /*
         * Assign the function pointer for searching the
         * data having address of the requested device.
         */
        find_buf.criteria_func = find_short_buffer;

        /* Update the short address to be searched. */
        find_buf.handle = &mac_parse_data.src_addr.short_address;
    }
    else if (mac_parse_data.src_addr_mode == FCF_LONG_ADDR)
    {
        /*
         * Look for pending data in the indirect queue for
         * this long address.
         */

        /*
         * Assign the function pointer for searching the
         * data having address of the requested device.
         */
        find_buf.criteria_func = find_long_buffer;

        /* Update the long address to be searched. */
        find_buf.handle = &mac_parse_data.src_addr.long_address;
    }
    else
    {
#if (DEBUG > 0)
            ASSERT("Unexpected addressing mode" == 0);
#endif
            return;
    }

    /*
     * Read from the indirect queue. The removal of items from this queue
     * will be done after successful transmission of the frame.
     */
    buf_ptr_next_data = qmm_queue_read(&indirect_data_q, &find_buf);
    /* Note: The find_buf structure is reused below, so do not change this. */

    if (NULL == buf_ptr_next_data)
    {
        mac_handle_tx_null_data_frame();
        return;
    }
    else
    {
        /* Indirect data found and to be sent. */
        transmit_frame = (frame_info_t *)BMM_BUFFER_POINTER(buf_ptr_next_data);

        /*
         * We need to check whether the source PAN-Id of the previously
         * received data request frame is identical to the destination PAN-Id
         * of the pending frame. If not the frame shall not be transmitted,
         * but a Null Data frame instead.
         */
        if (mac_parse_data.src_panid !=
            convert_byte_array_to_16_bit(&transmit_frame->mpdu[PL_POS_DST_PAN_ID_START])
           )
        {
            mac_handle_tx_null_data_frame();
            return;
        }
        else
        {
            /*
             * The frame to be transmitted next is marked.
             * This is necessary since the queue needs to be traversed again
             * to find other pending indirect data frames for this particular
             * recipient.
             */
            transmit_frame->indirect_in_transit = true;
            transmit_frame->buffer_header = buf_ptr_next_data;

            /*
             * Go through the indirect data queue to find out the frame pending for
             * the device which has requested for the data.
             */
            /*
             * Since the buffer header has already been stored in
             * transmit_frame->buffer_header, it can be reused here for
             * other purpose.
             */
            /*
             * It is assumed that the find_buf struct does still have
             * the original values from above.
             */
            buf_ptr_next_data = qmm_queue_read(&indirect_data_q, &find_buf);
            /*
             * Check whether there is another indirect data available
             * for the same recipient.
             */
            if (NULL != buf_ptr_next_data)
            {
                transmit_frame->mpdu[PL_POS_FCF_1] |= FCF_FRAME_PENDING;
            }
        }

        /*
         * Transmission should be done with CSMA-CA or
         * quickly after the ACK of the data request command.
         * Here it's done quickly after the ACK w/o CSMA.
         */
        tal_tx_status = tal_tx_frame(transmit_frame, NO_CSMA_WITH_IFS, false);

        if (MAC_SUCCESS == tal_tx_status)
        {
            MAKE_MAC_BUSY();
        }
        else
        {
            /*
             * TAL rejects frame transmission, since it's too close to the next
             * beacon transmission. The frame is kept in the indirect queue.
             */
            transmit_frame->indirect_in_transit = false;
        }
    }
} /* mac_process_data_request() */
Exemplo n.º 4
0
/**
 * @brief Notify the application when ZID report data is received from the paired device.
 *  
 * @param PairingRef Pairing reference.
 * @param num_report_records number of Report records.
 * @param *zid_report_data_record_ptr pointer to the report data received.
 * @param  RxLinkQuality    LQI value of the report data frame.
 * @param  RxFlags          Receive flags.
 */
static void zid_report_data_indication(uint8_t PairingRef, uint8_t num_report_records,
                                                zid_report_data_record_t *zid_report_data_record_ptr, uint8_t RxLinkQuality, uint8_t RxFlags)
{          
   
                  
                  
     for(uint8_t i=0;i<num_report_records;i++)
     {  
    
         switch(zid_report_data_record_ptr->report_desc_identifier)
         {
         case MOUSE:
         {
            
             mouse_desc_t *mouse_desc;
             mouse_desc = (mouse_desc_t *)zid_report_data_record_ptr->report_data;
			 
				udi_hid_mouse_btnleft(mouse_desc->button0); 
				udi_hid_mouse_btnright(mouse_desc->button1);
			   
				if((0x80==(mouse_desc->button2)))
				{   
					udi_hid_mouse_moveScroll((mouse_desc->y_coordinate));
					mouse_desc->y_coordinate = 0;
				}
				else if(0x01==(mouse_desc->button2))
				{ 
					udi_hid_mouse_btnmiddle(0x01);
				}
				udi_hid_mouse_moveX((mouse_desc->x_coordinate));
				udi_hid_mouse_moveY((mouse_desc->y_coordinate));
			 
          
             break;
         }
         case KEYBOARD:
         {
             if(zid_report_data_record_ptr->report_type == INPUT)
             {
                 
                 keyboard_input_desc_t *keyboard_input_desc;
                 keyboard_input_desc = (keyboard_input_desc_t *)zid_report_data_record_ptr->report_data;
                    if(main_b_kbd_enable)
                    {   
						if(keyboard_input_desc->modifier_keys)
						{
							udi_hid_kbd_modifier_down(keyboard_input_desc->modifier_keys);
							udi_hid_kbd_modifier_up(keyboard_input_desc->modifier_keys);
						}
					                    
						for(uint8_t j=0;j<4;j++)
						{  
							if(keyboard_input_desc->key_code[j])
							{    
								udi_hid_kbd_down(keyboard_input_desc->key_code[j]);
								udi_hid_kbd_up(keyboard_input_desc->key_code[j]);
							}   
                   
						}
						uint16_t u_value;
						u_value= convert_byte_array_to_16_bit(&(keyboard_input_desc->key_code[4]));
						if(u_value)
						{   
							udi_hid_mkbd_modifier_down(u_value);
							udi_hid_mkbd_modifier_up(u_value);
						}
					}
              
             }
             else
             {
                /* Application can implement for other report types.*/
             }
             break;
         }
         default:
		 break;
         }
         zid_report_data_record_ptr++;
     }

    RxLinkQuality = RxLinkQuality;
    RxFlags = RxFlags;

}
Exemplo n.º 5
0
static void handle_remote_range_req_frame(uint8_t *curr_frame_ptr)
{
    /*
     * Store addresses for the ongoing transaction.
     * This is required for all cases, also for
     * erroneous cases.
     */
    /* This node is the Initiator. */
    range_param.InitiatorAddrSpec.AddrMode = mac_parse_data.dest_addr_mode;
    range_param.InitiatorAddrSpec.PANId = mac_parse_data.dest_panid;
    /* Long address also covers short address here. */
    ADDR_COPY_DST_SRC_64(range_param.InitiatorAddrSpec.Addr.long_address,
                         mac_parse_data.dest_addr.long_address);

    /* The transmitter of this frame is the Coordinator. */
    /*
     * Note: Setting the Coordinator address mode here to a value different from
     * zero actually indicates, that remote ranging is ongoing.
     */
    range_param.CoordinatorAddrSpec.AddrMode = mac_parse_data.src_addr_mode;
    range_param.CoordinatorAddrSpec.PANId = mac_parse_data.src_panid;
    /* Long address also covers short address here. */
    ADDR_COPY_DST_SRC_64(range_param.CoordinatorAddrSpec.Addr.long_address,
                         mac_parse_data.src_addr.long_address);

    if (RTB_ROLE_NONE != rtb_role)
    {
        /* Ranging is currently already ongoing, do nothing. */
    }
    else if (!rtb_pib.RangingEnabled)
    {
        /* Ranging is currently disabled, reject new request. */
        range_status.range_error = (range_error_t)RTB_UNSUPPORTED_RANGING;
        rtb_state = RTB_INIT_REMOTE_RANGE_CONF_FRAME;
        /*
         * The role needs to be updated even in error
         * case to  be able to properly release the
         * frame buffer after the transmission of the
         * Remote Range confirm frame back to the Coordinator.
         */
        rtb_role = RTB_ROLE_INITIATOR;

        /*
         * Reset the PMU average data since no valid PMU average data are available
         * at this stage.
         */
        reset_pmu_average_data();
    }
    else
    {
        uint8_t frame_len;

        /*
         * Generally ranging is allowed ...
         * Now check requested ranging parameters.
         */

        /* Read Frame length field. */
        frame_len = *curr_frame_ptr++;

        if (RTB_PROTOCOL_VERSION_01 == *curr_frame_ptr++)
        {
            uint8_t refl_addr_len = IE_REFLECTOR_ADDR_SPEC_LEN_MIN;

            /* Currently only one RTB Protocol Version is supported. */

            rtb_role = RTB_ROLE_INITIATOR;

            /*
            * Reset the PMU average data since no valid PMU average data are available
            * at this stage.
            */
            reset_pmu_average_data();

            /* Extract Reflector address information from the frame. */
            refl_addr_t *ra =
                (refl_addr_t *)curr_frame_ptr;

            range_param.ReflectorAddrSpec.AddrMode = ra->refl_addr_mode;
            range_param.ReflectorAddrSpec.PANId = ra->refl_pan_id;
            /* Long address also covers short address here. */

            if (ra->refl_addr_mode == FCF_SHORT_ADDR)
            {
                range_param.ReflectorAddrSpec.Addr.long_address = 0;
                ADDR_COPY_DST_SRC_16(range_param.ReflectorAddrSpec.Addr.short_address,
                                     ra->refl_addr.short_address);
            }
            else
            {
                ADDR_COPY_DST_SRC_64(range_param.ReflectorAddrSpec.Addr.long_address,
                                     ra->refl_addr.long_address);
                refl_addr_len += 6;
            }
            curr_frame_ptr += refl_addr_len;

            /* Check whether requested ranging method is supported. */
            if (RTB_TYPE == *curr_frame_ptr++)
            {
                range_param.method = RTB_TYPE;

                range_param_pmu.f_start = convert_byte_array_to_16_bit(curr_frame_ptr);
                curr_frame_ptr += 2;
                range_param_pmu.f_step = *curr_frame_ptr++;
                range_param_pmu.f_stop = convert_byte_array_to_16_bit(curr_frame_ptr);
                curr_frame_ptr += 2;
                /*
                 * Extract remote range capabilities from
                 * the Coordinator.
                 */
                range_param.remote_caps = *curr_frame_ptr++;
                if (range_param.remote_caps & PMU_REM_CAP_APPLY_MIN_DIST_THRSHLD)
                {
                    range_param_pmu.apply_min_dist_threshold = true;
                }
                else
                {
                    range_param_pmu.apply_min_dist_threshold = false;
                }

                /*
                 * The capabilities for the actual ranging
                 * are not taken from the Coordinator, but
                 * rather from the Initiator itself.
                 */
                SET_INITIATOR_CAPS(range_param.caps);

                /*
                 * Initialize the Ranging Transmit Power to be applied at the
                 * Initiator in case this parameter is not included properly
                 * in this frame.
                 */
                range_param.req_tx_power = rtb_pib.RangingTransmitPower;

                /* Check wether Requested Ranging Transmit Power IE is available. */
                if (frame_len == IE_PMU_RANGING_LEN +
                    refl_addr_len +
                    IE_REQ_RANGING_TX_POWER_LEN)
                {
                    /*
                     * Extract and set requested Ranging Transmit Power
                     * (if changed).
                     */
                    if (REQ_RANGING_TX_POWER_IE == *curr_frame_ptr++)
                    {
                        /* Overwrite Ranging Transmit Power. */
                        range_param.req_tx_power = *curr_frame_ptr++;
                    }
                }

                if (!pmu_check_pmu_params())
                {
                    /* Unsupported ranging parameters, reject new request. */
                    range_status.range_error = (range_error_t)RTB_INVALID_PARAMETER;
                    rtb_state = RTB_INIT_REMOTE_RANGE_CONF_FRAME;
                }
                else
                {
                    /*
                     * Proper Remote Range Request frame received,
                     * so continue as Initiator.
                     */
#if (RTB_TYPE == RTB_PMU_233R)
                    /* Prepare FEC measurement */
                    pmu_enable_fec_measurement();
#endif  /* (RTB_TYPE == RTB_PMU_233R) */

                    configure_ranging();

#ifndef RTB_WITHOUT_MAC
                    /*
                     * Block MAC from doing anything else than ranging
                     * until this procedure is finished.
                     */
                    MAKE_MAC_BUSY();
#endif  /* #ifndef RTB_WITHOUT_MAC */

                    /*
                     * Next a Range Request frame needs to be assembled to be
                     * transmitted to Reflector
                     */
                    range_status.range_error = RANGE_OK;
                    rtb_state = RTB_INIT_RANGE_REQ_FRAME;
                }
            }
            else
            {
                /* Unsupported ranging method, reject new request. */
                range_status.range_error = (range_error_t)RTB_UNSUPPORTED_METHOD;
                rtb_state = RTB_INIT_REMOTE_RANGE_CONF_FRAME;
            }
        }
        else    /* if (RTB_PROTOCOL_VERSION_01 == *curr_frame_ptr++) */
        {
            /* Unsupported RTB Protocol Version, reject new request. */
            range_status.range_error = (range_error_t)RTB_UNSUPPORTED_PROTOCOL;
            rtb_state = RTB_INIT_REMOTE_RANGE_CONF_FRAME;
        }
    }
}
Exemplo n.º 6
0
static void handle_range_req_frame(uint8_t *curr_frame_ptr)
{
    /*
     * Store addresses for the ongoing transaction.
     * This is required for all cases, also for
     * erroneous cases.
     */
    /* This node is the Reflector. */
    range_param.ReflectorAddrSpec.AddrMode = mac_parse_data.dest_addr_mode;
    range_param.ReflectorAddrSpec.PANId = mac_parse_data.dest_panid;
    /* Long address also covers short address here. */
    ADDR_COPY_DST_SRC_64(range_param.ReflectorAddrSpec.Addr.long_address,
                         mac_parse_data.dest_addr.long_address);

    /* The transmitter of this frame is the Initiator. */
    range_param.InitiatorAddrSpec.AddrMode = mac_parse_data.src_addr_mode;
    range_param.InitiatorAddrSpec.PANId = mac_parse_data.src_panid;
    /* Long address also covers short address here. */
    ADDR_COPY_DST_SRC_64(range_param.InitiatorAddrSpec.Addr.long_address,
                         mac_parse_data.src_addr.long_address);

    if (RTB_ROLE_NONE != rtb_role)
    {
        /* Ranging is currently already ongoing, do nothing. */
    }
    else if (!rtb_pib.RangingEnabled)
    {
        /* Ranging is currently disabled, reject new request. */
        range_status.range_error = (range_error_t)RTB_UNSUPPORTED_RANGING;
        rtb_state = RTB_INIT_RANGE_ACPT_FRAME;
        /*
         * The role needs to be updated even in error
         * case to  be able to properly release the
         * frame buffer after the transmission of the
         * Range Accept frame back to the Initiator.
         */
        rtb_role = RTB_ROLE_REFLECTOR;

        /*
         * Reset the PMU average data since no valid PMU average data are available
         * at this stage.
         */
        reset_pmu_average_data();
    }
    else
    {
        uint8_t frame_len;

        rtb_role = RTB_ROLE_REFLECTOR;

        /*
         * Reset the PMU average data since no valid PMU average data are available
         * at this stage.
         */
        reset_pmu_average_data();

        /*
         * Generally ranging is allowed ...
         * Now check requested ranging parameters.
         */

        /* Read Frame length field. */
        frame_len = *curr_frame_ptr++;

        if (RTB_PROTOCOL_VERSION_01 == *curr_frame_ptr++)
        {
            /* Currently only one RTB Protocol Version is supported. */

            /* Check whether requested ranging method is supported. */
            if (RTB_TYPE == *curr_frame_ptr++)
            {
                range_param.method = RTB_TYPE;

                range_param_pmu.f_start = convert_byte_array_to_16_bit(curr_frame_ptr);
                curr_frame_ptr += 2;
                range_param_pmu.f_step = *curr_frame_ptr++;
                range_param_pmu.f_stop = convert_byte_array_to_16_bit(curr_frame_ptr);;
                curr_frame_ptr += 2;

                range_param.caps = *curr_frame_ptr++;
                /*
                 * Update the received capabilities from the Initiator
                 * to match our own capabilities.
                 *
                 * Note: Other capabilty bits than used for antenna
                 * diversity are not touched here.
                 */
#if (ANTENNA_DIVERSITY == 1)
                /*
                 * If we allow antenna diversity generally,
                 * use antenna diversity value received from the initiator,
                 * and simply update our own.
                 */
                if (rtb_pib.EnableAntennaDiv)
                {
                    /*
                     * Reflector uses antenna diversity.
                     * Keep Initiator antenna diversity as is.
                     */
                    range_param.caps |= PMU_CAP_REFLECTOR_ANT;
                }
                else
                {
                    /*
                     * Reflector temporarily does not use antenna diversity,
                     * but keep Initiator antenna diversity as is.
                     */
                    range_param.caps &= ~(PMU_CAP_REFLECTOR_ANT);
                }
#else
                /*
                 * Reflector generally does not use antenna diversity,
                 * but keep Initiator antenna diversity as is.
                 */
                range_param.caps &= ~(PMU_CAP_REFLECTOR_ANT);

#endif  /* (ANTENNA_DIVERSITY == 1) */

                /*
                 * Initialize the Ranging Transmit Power to be applied at the
                 * Reflector in case this parameter is not included properly
                 * in this frame.
                 */
                range_param.req_tx_power = rtb_pib.RangingTransmitPower;

                /* Check wether Requested Ranging Transmit Power IE is available. */
                if (frame_len == IE_PMU_RANGING_LEN + IE_REQ_RANGING_TX_POWER_LEN)
                {
                    /*
                     * Extract and set requested Ranging Transmit Power
                     * (if changed).
                     */
                    if (REQ_RANGING_TX_POWER_IE == *curr_frame_ptr++)
                    {
                        /* Overwrite Ranging Transmit Power. */
                        range_param.req_tx_power = *curr_frame_ptr++;
                    }
                }

                pmu_configure_antenna();

                if (!pmu_check_pmu_params())
                {
                    /* Unsupported ranging parameters, reject new request. */
                    range_status.range_error = (range_error_t)RTB_INVALID_PARAMETER;
                    rtb_state = RTB_INIT_RANGE_ACPT_FRAME;
                }
                else
                {
#if (RTB_TYPE == RTB_PMU_233R)
                    /* Prepare FEC measurement */
                    pmu_enable_fec_measurement();
#endif  /* (RTB_TYPE == RTB_PMU_233R) */

                    configure_ranging();

#ifndef RTB_WITHOUT_MAC
                    /*
                     * Block MAC from doing anything else than ranging
                     * until this procedure is finished.
                     */
                    MAKE_MAC_BUSY();
#endif  /* #ifndef RTB_WITHOUT_MAC */

                    /* Next a Range Accept frame needs to be assembled. */
                    range_status.range_error = RANGE_OK;
                    rtb_state = RTB_INIT_RANGE_ACPT_FRAME;
                }
            }
            else
            {
                /* Unsupported ranging method, reject new request. */
                range_status.range_error = (range_error_t)RTB_UNSUPPORTED_METHOD;
                rtb_state = RTB_INIT_RANGE_ACPT_FRAME;
            }
        }
        else    /* if (RTB_PROTOCOL_VERSION_01 == *curr_frame_ptr++) */
        {
            /* Unsupported RTB Protocol Version, reject new request. */
            range_status.range_error = (range_error_t)RTB_UNSUPPORTED_PROTOCOL;
            rtb_state = RTB_INIT_RANGE_ACPT_FRAME;
        }
    }
}
Exemplo n.º 7
0
/*
 * @brief Handles received RTB frames
 *
 * This function parses a received MPDU and checks whether this frame
 * is dedicated to the RTB.
 *
 * @param rx_frame_ptr Pointer to frame received from TAL
 *
 * @return bool True if frame is for RTB, or false if frame is for MAC.
 */
static bool handle_rx_rtb_frame_type(frame_info_t *rx_frame_ptr)
{
    uint8_t payload_index = 0;
    uint16_t fcf;
    range_cmd_t rcmd;
    bool rtb_frame_handled = false;
    uint8_t *temp_frame_ptr = &(rx_frame_ptr->mpdu[1]);
    /* temp_frame_ptr points now to first octet of FCF. */

    /* Extract the FCF. */
    fcf = convert_byte_array_to_16_bit(temp_frame_ptr);
    fcf = CLE16_TO_CPU_ENDIAN(fcf);
    mac_parse_data.fcf = fcf;
    temp_frame_ptr += 2;

    /* Extract the Sequence Number. */
    mac_parse_data.sequence_number = *temp_frame_ptr++;

    /* Extract the complete address information from the MHR. */
    temp_frame_ptr += mac_extract_mhr_addr_info(temp_frame_ptr);
    /*
     * Note: temp_frame_ptr points now to the first octet of the MAC payload
     * if available.
     */

    mac_parse_data.frame_type = FCF_GET_FRAMETYPE(fcf);

    if (FCF_FRAMETYPE_DATA == mac_parse_data.frame_type)
    {
        /* This is a data frame - continue. */
        if (mac_parse_data.mac_payload_length)
        {
            /*
             * In case the device got a frame with a corrupted payload
             * length
             */
            if (mac_parse_data.mac_payload_length >= aMaxMACPayloadSize)
            {
                mac_parse_data.mac_payload_length = aMaxMACPayloadSize;
            }

            /*
             * Copy the pointer to the data frame payload for
             * further processing later.
             */
            mac_parse_data.mac_payload_data.data.payload = &temp_frame_ptr[payload_index];

            /* Check RTB frame identifier. */
            if ((*temp_frame_ptr++ == RTB_FRAME_ID_1) &&
                (*temp_frame_ptr++ == RTB_FRAME_ID_2) &&
                (*temp_frame_ptr++ == RTB_FRAME_ID_3)
               )
            {
                /* This frame is an RTB frame. */

                /* Frame is data frame with payload. */
                /* Check whether the data frame is a valid ranging frame. */
                rcmd = (range_cmd_t)(*temp_frame_ptr);
                temp_frame_ptr++;

                switch (rcmd)
                {
                    case CMD_RANGE_REQ:
                        {
                            handle_range_req_frame(temp_frame_ptr);

                            /* Frame has been handled within RTB. */
                            rtb_frame_handled = true;
                        }
                        break;

                    case CMD_RANGE_ACPT:
                        {
                            handle_range_acpt_frame(temp_frame_ptr);

                            /* Frame has been handled within RTB. */
                            rtb_frame_handled = true;
                        }
                        break;

#ifdef ENABLE_RTB_REMOTE
                    case CMD_REMOTE_RANGE_REQ:
                        {
                            /* This is a remote range request frame. */
                            handle_remote_range_req_frame(temp_frame_ptr);

                            /* Frame has been handled within RTB. */
                            rtb_frame_handled = true;
                        }
                        break;
#endif  /* ENABLE_RTB_REMOTE */

#ifdef ENABLE_RTB_REMOTE
                    case CMD_REMOTE_RANGE_CONF:
                        {
                            handle_remote_range_conf_frame(temp_frame_ptr);

                            /* Frame has been handled within RTB. */
                            rtb_frame_handled = true;
                        }
                        break;
#endif  /* ENABLE_RTB_REMOTE */

                    case CMD_PMU_TIME_SYNC_REQ:
                        {
                            if (RTB_ROLE_REFLECTOR == rtb_role)
                            {
                                handle_pmu_time_sync_frame();

                                /* Frame has been handled within RTB. */
                                rtb_frame_handled = true;

                                /* Buffer is freed up in the calling function. */
                            }
                        }
                        break;
					
                    case CMD_RESULT_REQ:
                        {
                            /* This is a result request frame. */
                            if (RTB_ROLE_REFLECTOR == rtb_role)
                            {
                                handle_result_req_frame(temp_frame_ptr);

                                /* Frame has been handled within RTB. */
                                rtb_frame_handled = true;

                                /* Buffer is freed up in the calling function. */
                            }
                        }
                        break;

                    case CMD_RESULT_CONF:
                        {
                            /* This is a result confirm frame. */
                            if ((RTB_ROLE_INITIATOR == rtb_role) &&
                                (RTB_AWAIT_RESULT_CONF_FRAME == rtb_state))
                            {
                                handle_result_conf_frame(temp_frame_ptr);

                                /* Frame has been handled within RTB. */
                                rtb_frame_handled = true;

                                /* Buffer is freed up in the calling function. */
                            }
                        }
                        break;

                    default:
/*#ifndef ENABLE_RTB_PRINT
					    printf("Unknown RX command to process: 0x%x", rcmd);	
#endif	*/				
                        break;
                }   /* switch (rcmd) */
            }   /* This frame is an RTB frame. */
        }
        else
        {
            mac_parse_data.mac_payload_length = 0;
            /* Data frame without payload is NOT for RTB. */
        }
    }

    return rtb_frame_handled;
} /* handle_rx_rtb_frame_type() */