/* if we wanted to find out what we sent (i.e. when we get an ack) */ bool tsm_get_transaction_pdu( uint8_t invokeID, BACNET_ADDRESS * dest, BACNET_NPDU_DATA * ndpu_data, uint8_t * apdu, uint16_t * apdu_len) { uint16_t j = 0; uint8_t index; bool found = false; if (invokeID) { index = tsm_find_invokeID_index(invokeID); /* how much checking is needed? state? dest match? just invokeID? */ if (index < MAX_TSM_TRANSACTIONS) { /* FIXME: we may want to free the transaction so it doesn't timeout */ /* retrieve the transaction */ /* FIXME: bounds check the pdu_len? */ *apdu_len = (uint16_t) TSM_List[index].apdu_len; for (j = 0; j < *apdu_len; j++) { apdu[j] = TSM_List[index].apdu[j]; } npdu_copy_data(ndpu_data, &TSM_List[index].npdu_data); bacnet_address_copy(dest, &TSM_List[index].dest); found = true; } } return found; }
void tsm_set_confirmed_unsegmented_transaction( uint8_t invokeID, BACNET_ADDRESS * dest, BACNET_NPDU_DATA * ndpu_data, uint8_t * apdu, uint16_t apdu_len) { uint16_t j = 0; uint8_t index; if (invokeID) { index = tsm_find_invokeID_index(invokeID); if (index < MAX_TSM_TRANSACTIONS) { /* SendConfirmedUnsegmented */ TSM_List[index].state = TSM_STATE_AWAIT_CONFIRMATION; TSM_List[index].RetryCount = 0; /* start the timer */ TSM_List[index].RequestTimer = apdu_timeout(); /* copy the data */ for (j = 0; j < apdu_len; j++) { TSM_List[index].apdu[j] = apdu[j]; } TSM_List[index].apdu_len = apdu_len; npdu_copy_data(&TSM_List[index].npdu_data, ndpu_data); bacnet_address_copy(&TSM_List[index].dest, dest); } } return; }
/* frees the invokeID and sets its state to IDLE */ void tsm_free_invoke_id( uint8_t invokeID) { uint8_t index; index = tsm_find_invokeID_index(invokeID); if (index < MAX_TSM_TRANSACTIONS) { TSM_List[index].state = TSM_STATE_IDLE; TSM_List[index].InvokeID = 0; } }
/** Check if the invoke ID has been made free by the Transaction State Machine. * @param invokeID [in] The invokeID to be checked, normally of last message sent. * @return True if it is free (done with), False if still pending in the TSM. */ bool tsm_invoke_id_free( uint8_t invokeID) { bool status = true; uint8_t index; index = tsm_find_invokeID_index(invokeID); if (index < MAX_TSM_TRANSACTIONS) status = false; return status; }
/** See if we failed get a confirmation for the message associated * with this invoke ID. * @param invokeID [in] The invokeID to be checked, normally of last message sent. * @return True if already failed, False if done or segmented or still waiting * for a confirmation. */ bool tsm_invoke_id_failed( uint8_t invokeID) { bool status = false; uint8_t index; index = tsm_find_invokeID_index(invokeID); if (index < MAX_TSM_TRANSACTIONS) { /* a valid invoke ID and the state is IDLE is a message that failed to confirm */ if (TSM_List[index].state == TSM_STATE_IDLE) status = true; } return status; }
/* gets the next free invokeID, and reserves a spot in the table returns 0 if none are available */ uint8_t tsm_next_free_invokeID( void) { uint8_t index = 0; uint8_t invokeID = 0; bool found = false; /* is there even space available? */ if (tsm_transaction_available()) { while (!found) { index = tsm_find_invokeID_index(Current_Invoke_ID); if (index == MAX_TSM_TRANSACTIONS) { /* Not found, so this invokeID is not used */ found = true; /* set this id into the table */ index = tsm_find_first_free_index(); if (index != MAX_TSM_TRANSACTIONS) { TSM_List[index].InvokeID = invokeID = Current_Invoke_ID; TSM_List[index].state = TSM_STATE_IDLE; TSM_List[index].RequestTimer = apdu_timeout(); /* update for the next call or check */ Current_Invoke_ID++; /* skip zero - we treat that internally as invalid or no free */ if (Current_Invoke_ID == 0) { Current_Invoke_ID = 1; } } } else { /* found! This invokeID is already used */ /* try next one */ Current_Invoke_ID++; /* skip zero - we treat that internally as invalid or no free */ if (Current_Invoke_ID == 0) { Current_Invoke_ID = 1; } } } } return invokeID; }