Esempio n. 1
0
/**
 * Calculates number of hashes from stdin or from files 
 *
 * Expected input ./gethash [-md5] [-c16] [-c32] [-xor] [-hex] [-f file]
 */
int main( int argc, char *argv[] )
{

   unsigned char hash = 0;
   FILE *file = stdin;

   parse_args(argc, argv, &hash, &file);

   unsigned int length;
   unsigned char *data = read_file(file, &length);
   

   printf("Length: %i bytes\n", length);

   if(hash & XOR){
      printf("XOR: ");
      if(hash & HEX)
         printf("0x%02x\n", xor_compute(data, length));
      else
         printf("%u\n", xor_compute(data, length));
   }

   if(hash & C16){
      printf("CRC-16: ");
      if(hash & HEX)
         printf("0x%04x\n", crc16_compute(data, length));
      else
         printf("%u\n", crc16_compute(data, length));
   }

   if(hash & C32){
      printf("CRC-32: ");
      if(hash & HEX)
         printf("0x%08x\n", crc32_compute(data, length));
      else
         printf("%u\n", crc32_compute(data, length));
   }

   if(hash & MD5){
      unsigned char result[16];
      md5_compute(data, length, result);

      printf("MD5: ");
      for (int i = 0; i < 16; i++){
         printf("%02x", result[i]);
      }
      printf("\n");
   }

   free(data);
   fclose(file);

   return 0;
}
bool bootloader_app_is_valid(uint32_t app_addr)
{
    const bootloader_settings_t * p_bootloader_settings;

    // There exists an application in CODE region 1.
    if (*((uint32_t *)app_addr) == EMPTY_FLASH_MASK)
    {
        return false;
    }

    bool success = false;

    bootloader_util_settings_get(&p_bootloader_settings);

    // The application in CODE region 1 is flagged as valid during update.
    if (p_bootloader_settings->bank_0 == BANK_VALID_APP)
    {
        uint16_t image_crc = 0;

        // A stored crc value of 0 indicates that CRC checking is not used.
        if (p_bootloader_settings->bank_0_crc != 0)
        {
            image_crc = crc16_compute((uint8_t *)DFU_BANK_0_REGION_START,
                                      p_bootloader_settings->bank_0_size,
                                      NULL);
        }

        success = (image_crc == p_bootloader_settings->bank_0_crc);
    }

    return success;
}
uint32_t dfu_init_postvalidate(uint8_t * p_image, uint32_t image_len)
{
#if NEED_CRC_CHECK /* disabled for now */
    uint16_t image_crc;
    uint16_t received_crc;
    
    // In order to support hashing (and signing) then the (decrypted) hash should be fetched and
    // the corresponding hash should be calculated over the image at this location.
    // If hashing (or signing) is added to the system then the CRC validation should be removed.

    // calculate CRC from active block.
    image_crc = crc16_compute(p_image, image_len, NULL);

    // Decode the received CRC from extended data.    
    received_crc = uint16_decode((uint8_t *)&m_extended_packet[0]);

    // Compare the received and calculated CRC.
    if (image_crc != received_crc)
    {
        return NRF_ERROR_INVALID_DATA;
    }
#endif /* NEED_CRC_CHECK */

    return NRF_SUCCESS;
}
Esempio n. 4
0
void BLE_init()
{
    ble_stack_init();
    gap_params_init();
    services_init();
    sec_params_init();
    
    ble_gap_addr_t MAC;
    sd_ble_gap_address_get(&MAC);
    debug_log("MAC address: %.2X:%.2X:%.2X:%.2X:%.2X:%.2X", MAC.addr[5],MAC.addr[4],MAC.addr[3],
                                                                MAC.addr[2],MAC.addr[1],MAC.addr[0]);
    
    defaultID = crc16_compute(MAC.addr,6,NULL);  // compute default badge ID from MAC address
    debug_log("-->default ID: 0x%hX\r\n",defaultID);
    badgeAssignment.ID = defaultID;
    badgeAssignment.group = NO_GROUP;
    
    // Copy MAC address into custom advertising data struct.
    for(int i = 0; i <= 5; i++)  { 
        customAdvData.MAC[i] = MAC.addr[i];
    }
    
    //advertising_init();
    //uint32_t err_code = ble_advertising_start(BLE_ADV_MODE_FAST);
    //BLE_ERROR_CHECK(err_code);
}
Esempio n. 5
0
bool bridge_create_tx_packet(uint8_t command, uint8_t len, uint8_t * data)
{
    bridge.tx.packet.command = command;
    bridge.tx.packet.payload_length = len;
    memcpy((uint8_t *)bridge.tx.packet.payload, data, len);
    bridge.tx.packet.crc16 = crc16_compute((uint8_t *)&bridge.tx.packet, bridge.tx.packet.payload_length + BRIDGE_HEDER_SIZE, NULL);  
    return true;
}
Esempio n. 6
0
static uint32_t s_hal_crc16_sw_compute(hal_crc_info_t *info, const void *data, uint32_t size)
{
    uint8_t tailsize = size%4;

    uint32_t size4 = size-tailsize;

    info->initialvalue = crc16_compute(info->cfg.crctblram, info->initialvalue, (uint8_t*)data, size4);
   
    if(0 != (tailsize))
    {
        uint8_t tail[4];
        memset(tail, 0, 4);
        memcpy(tail, ((uint8_t*)data) + size-tailsize, tailsize);
        info->initialvalue = crc16_compute(info->cfg.crctblram, info->initialvalue, tail, 4); 
    }

    return(info->initialvalue);
}
uint32_t dfu_image_validate()
{
    uint32_t err_code;
    uint16_t received_crc;    
    
    switch (m_dfu_state)
    {
        case DFU_STATE_RX_DATA_PKT:
            m_dfu_state = DFU_STATE_VALIDATE;
            
            // Check if the application image write has finished.
            if (m_app_data_received != m_image_size)
            {
                // Image not yet fully transfered by the peer or the peer has attempted to write
                // too much data. Hence the validation should fail.
                err_code = NRF_ERROR_INVALID_STATE;
            }
            else
            {                        
                // Valid peer activity detected. Hence restart the DFU timer.
                err_code = dfu_timer_restart();
                if (err_code == NRF_SUCCESS)
                {                    
                    // calculate CRC from DFU_BANK_1_REGION_START to mp_app_write_address.
                    m_image_crc  = crc16_compute((uint8_t*)DFU_BANK_1_REGION_START, 
                                                 m_image_size, 
                                                 NULL);
                    received_crc = uint16_decode((uint8_t*)&m_init_packet[0]);
                    
                    if ((m_init_packet_length != 0) && (m_image_crc != received_crc))
                    {
                        return NRF_ERROR_INVALID_DATA;
                    }                    
                    
                    m_dfu_state = DFU_STATE_WAIT_4_ACTIVATE;                                                                                
                }
            }
            break;
            
        default:
            err_code = NRF_ERROR_INVALID_STATE;
            break;              
    }
    
    return err_code;        
}
Esempio n. 8
0
/**@brief Function for validating a received packet.
 *
 * @param[in] p_buffer Pointer to the packet data.
 * @param[in] length   Length of packet data in bytes.
 *
 * @return true if received packet is valid, false in other case.
 */
static bool is_rx_pkt_valid(const uint8_t * p_buffer, uint32_t length)
{
    // Executed packet filtering algorithm order:
    // - verify packet overall length
    // - verify data integrity bit set
    // - verify reliable packet bit set
    // - verify supported packet type
    // - verify header checksum
    // - verify payload length field
    // - verify CRC
    if (length <= PKT_HDR_SIZE)
    {
        return false;
    }

    if (!(p_buffer[0] & DATA_INTEGRITY_MASK))
    {
        return false;
    }

    if (!(p_buffer[0] & RELIABLE_PKT_MASK))
    {
        return false;
    }

    if ((p_buffer[1] & 0x0Fu) != PKT_TYPE_VENDOR_SPECIFIC)
    {
        return false;
    }

    const uint32_t expected_checksum =
        ((p_buffer[0] + p_buffer[1] + p_buffer[2] + p_buffer[3])) & 0xFFu;
    if (expected_checksum != 0)
    {
        return false;
    }

    const uint16_t crc_calculated = crc16_compute(p_buffer, (length - PKT_CRC_SIZE), NULL);
    const uint16_t crc_received   = uint16_decode(&p_buffer[length - PKT_CRC_SIZE]);
    if (crc_calculated != crc_received)
    {
        return false;
    }

    return true;
}
bool bootloader_app_is_valid(uint32_t app_addr)
{
    // There exists an application in CODE region 1.
    if (DFU_BANK_0_REGION_START == EMPTY_FLASH_MASK)
    {
        return false;
    }

#if 0
    const bootloader_settings_t * p_bootloader_settings;
    bool success = false;

    switch (app_addr)
    {
        case DFU_BANK_0_REGION_START:
            bootloader_util_settings_get(&p_bootloader_settings);

            // The application in CODE region 1 is flagged as valid during update.
            if (p_bootloader_settings->bank_0 == BANK_VALID_APP)
            {
                uint16_t image_crc = 0;

                // A stored crc value of 0 indicates that CRC checking is not used.
                if (p_bootloader_settings->bank_0_crc != 0)
                {
                    image_crc = crc16_compute((uint8_t*)DFU_BANK_0_REGION_START,
                                              p_bootloader_settings->bank_0_size,
                                              NULL);
                }

                success = (image_crc == p_bootloader_settings->bank_0_crc);
            }
            break;

        case DFU_BANK_1_REGION_START:
        default:
            // No implementation needed.
            break;
    }

    return success;
#else
    return true;
#endif
}
static void send_single_packet()
{
    uint16_t crc;
    uint32_t data_offset;
    
    // Include the length
    spim_com_tx_transaction.fields.len_lsb  = (uint8_t)m_spim_com_tx_packet_length;
    spim_com_tx_transaction.fields.len_msb  = (uint8_t)(m_spim_com_tx_packet_length >> 8);
    
    data_offset = (uint32_t)m_spim_com_tx_packet_fragment_num * SPI_COM_PCK_DATA_SIZE;
    
    if((m_spim_com_tx_packet_length - data_offset) > SPI_COM_PCK_DATA_SIZE)
    {
        memcpy(spim_com_tx_transaction.fields.data, m_spim_com_tx_packet + data_offset, SPI_COM_PCK_DATA_SIZE);
    }
    else
    {
        memcpy(spim_com_tx_transaction.fields.data, m_spim_com_tx_packet + data_offset, m_spim_com_tx_packet_length - data_offset);
        memset(spim_com_tx_transaction.fields.data + (m_spim_com_tx_packet_length - data_offset), 0, SPI_COM_PCK_DATA_SIZE - (m_spim_com_tx_packet_length - data_offset));
    }
    
    // Calculate and include the CRC
    spim_com_tx_transaction.fields.crc_lsb  = 0;
    spim_com_tx_transaction.fields.crc_msb  = 0;
    crc = crc16_compute(spim_com_tx_transaction.data, SPI_COM_MAX_TRANSACTION_SIZE, 0);
    spim_com_tx_transaction.fields.crc_lsb  = (uint8_t)crc;
    spim_com_tx_transaction.fields.crc_msb  = (uint8_t)(crc >> 8);
       
    // Assert the RDY signal
    nrf_gpio_pin_clear(m_spim_com_pin_reqn);
    
    // Wait for the REQ line to be asserted by the slave
    while(nrf_gpio_pin_read(m_spim_com_pin_rdyn) != 0);
    
    // De-assert the RDY signal
    nrf_gpio_pin_set(m_spim_com_pin_reqn);

    m_spim_com_tx_packet_fragment_num++; 
    
    spi_master_send_recv(SPI_MASTER_0, spim_com_tx_transaction.data, SPI_COM_MAX_TRANSACTION_SIZE, spim_com_rx_transaction.data, SPI_COM_MAX_TRANSACTION_SIZE);  
}
Esempio n. 11
0
uint32_t dfu_image_validate()
{
    uint32_t err_code;
    uint16_t received_crc;    

    switch (m_dfu_state)
    {
        case DFU_STATE_RX_DATA_PKT:
            m_dfu_state = DFU_STATE_VALIDATE;
            
            // Check if the application image write has finished.
            if (m_received_data != m_image_size)
            {
                // Image not yet fully transferred by the peer.
                err_code = NRF_ERROR_INVALID_STATE;
            }
            else
            {
                // Calculate CRC from DFU_BANK_0_REGION_START to mp_app_write_address.
                m_image_crc  = crc16_compute((uint8_t*)DFU_BANK_0_REGION_START, 
                                             m_image_size, 
                                             NULL);
                received_crc = uint16_decode((uint8_t*)&m_init_packet[0]);
                    
                if ((m_init_packet_length != 0) && (m_image_crc != received_crc))
                {
                    return NRF_ERROR_INVALID_DATA;
                }
                m_dfu_state = DFU_STATE_WAIT_4_ACTIVATE;
                err_code    = NRF_SUCCESS;
            }

            break;            
            
        default:
            err_code = NRF_ERROR_INVALID_STATE;
            break;  
    }
    
    return err_code;    
}
Esempio n. 12
0
bool bootloader_app_is_valid(uint32_t app_addr)
{
    const bootloader_settings_t * p_bootloader_settings;

    // There exists an application in CODE region 1.
    if (*((uint32_t *)app_addr) == EMPTY_FLASH_MASK)
    {
        return false;
    }

    bool success = false;

    bootloader_util_settings_get(&p_bootloader_settings);
#if DEBUG_BOOTLOADER_EN
  //simple_uart_init();
  DbgPrintf_str("\r\ncheck bootloader_app_is_valid,bank_0:"); 
  DbgPrintf_hex(p_bootloader_settings->bank_0);
  DbgPrintf_str("crc:"); 
  DbgPrintf_hex(p_bootloader_settings->bank_0_crc);
  DbgPrintf_str("size:"); 
  DbgPrintf_hex(p_bootloader_settings->bank_0_size);
#endif
    // The application in CODE region 1 is flagged as valid during update.
    if (p_bootloader_settings->bank_0 == BANK_VALID_APP)
    {
        uint16_t image_crc = 0;

        // A stored crc value of 0 indicates that CRC checking is not used.
        if (p_bootloader_settings->bank_0_crc != 0)
        {
            image_crc = crc16_compute((uint8_t *)DFU_BANK_0_REGION_START,
                                      p_bootloader_settings->bank_0_size,
                                      NULL);
        }

        success = (image_crc == p_bootloader_settings->bank_0_crc);
    }

    return success;
}
Esempio n. 13
0
/**@brief Function for handling the application packet write request in tx-idle state.
 */
static uint32_t pkt_write_handle(void)
{
    uint32_t err_code;

    // Set packet header fields.

    mp_tx_buffer   -= PKT_HDR_SIZE;
    mp_tx_buffer[0] = tx_packet_byte_zero_construct();

    const uint16_t type_and_length_fields = ((m_tx_buffer_length << 4u) | PKT_TYPE_VENDOR_SPECIFIC);
    // @note: no use case for uint16_encode(...) return value.
    UNUSED_VARIABLE(uint16_encode(type_and_length_fields, &(mp_tx_buffer[1])));
    mp_tx_buffer[3] = header_checksum_calculate(mp_tx_buffer);

    // Calculate, append CRC to the packet and write it.

    const uint16_t crc = crc16_compute(mp_tx_buffer, (PKT_HDR_SIZE + m_tx_buffer_length), NULL);
    // @note: no use case for uint16_encode(...) return value.
    UNUSED_VARIABLE(uint16_encode(crc, &(mp_tx_buffer[PKT_HDR_SIZE + m_tx_buffer_length])));
    err_code = hci_slip_write(mp_tx_buffer, (m_tx_buffer_length + PKT_HDR_SIZE + PKT_CRC_SIZE));
    switch (err_code)
    {
        case NRF_SUCCESS:
            tx_sm_state_change(TX_STATE_ACTIVE);
            break;

        case NRF_ERROR_NO_MEM:
            tx_sm_state_change(TX_STATE_PENDING);
            err_code = NRF_SUCCESS;
            break;

        default:
            // No implementation needed.
            break;
    }

    return err_code;
}
Esempio n. 14
0
buf32_t* malloc_HciPacket(buf32_t* pFrame)
{
    uint16_t crc;
    buf32_t *pEncoded_STATIC;
    buf32_t *pSlipPkt;
    buf32_t *pTemp;

    static uint8_t _temp_buffer[4 + 4+512 + 2];
    static buf32_t _temp;
    
    _temp.buffer = _temp_buffer;
    _temp.capacity =  sizeof(_temp_buffer ); //4 + 4+512 + 2;
    pTemp = &_temp;

    //----------------------
    //    Add HCI Header
    //----------------------
    HciPacket.sequence_number = (HciPacket.sequence_number+1) % 8;
    buf32_zero(pTemp);
    buf32_join(pTemp, buf32_parts_to_four_bytes( HciPacket.sequence_number, 
                                                 DATA_INTEGRITY_CHECK_PRESENT,
                                                 RELIABLE_PACKET,
                                                 HCI_PACKET_TYPE,
                                                 pFrame->length) );
    //buf32_print("## 0", pTemp);

    //-------------------
    //    Add payload 
    //-------------------
    buf32_join(pTemp, pFrame);
    //// Add escape caracters
    //buf32_print("## 1", pTemp);

    //---------------
    //    Add CRC    
    //---------------
    crc = 0xFFFF;
    crc = crc16_compute(pTemp->buffer, pTemp->length, &crc);

    pTemp->buffer[pTemp->length] = (uint8_t)(crc & 0xFF);          pTemp->length++; //chr(crc & 0xFF)
    pTemp->buffer[pTemp->length] = (uint8_t)((crc & 0xFF00) >> 8); pTemp->length++; //chr((crc & 0xFF00) >> 8)
    //buf32_print("## 2", pTemp);


    //------------------------
    //    Do SLIP encoding
    //------------------------
    pEncoded_STATIC = buf32_slip_encode_packet(pTemp);
    //buf32_print("## pEncoded_STATIC", pEncoded_STATIC);


    //---------------------------------
    //    Add 0xC0 to start and end
    //---------------------------------
    pSlipPkt = buf32_Create(1 + pEncoded_STATIC->length + 1);

    //buf32_zero(pSlipPkt);    
    pSlipPkt->length = 0;
    pSlipPkt->buffer[pSlipPkt->length] = 0xC0;  //self->buffer = chr(0xc0)
    pSlipPkt->length++;
    //buf32_print("## pSlipPkt", pSlipPkt);

    buf32_join(pSlipPkt, pEncoded_STATIC);             //self->buffer += self.temp_data
    //buf32_print("## pSlipPkt", pSlipPkt);
    
    pSlipPkt->buffer[pSlipPkt->length] = 0xC0;  //self->buffer += chr(0xc0)
    pSlipPkt->length++;
    //buf32_print("## pSlipPkt", pSlipPkt);

    return(pSlipPkt);
}
Esempio n. 15
0
//#include "memory.h"
//#include "stdlib.h" //malloc
int32_t make_HciPacket_cb16(uint8_t* pDin, uint16_t lenDin, cb16_t* cbOut, uint16_t* plenDout )
{
    uint16_t  totalLength;
    uint16_t  crc;

    uint16_t  i;

    uint8_t*  pdata4;
    uint8_t len12;
    uint8_t b0;
    uint8_t b1;
    uint8_t  crc01[2];


    if( cbOut != 0) 
        W_HciPacket.sequence_number = (W_HciPacket.sequence_number+1) % 8;

    pdata4 = bytePtr_parts_to_four_bytes( W_HciPacket.sequence_number, 
                                          DATA_INTEGRITY_CHECK_PRESENT,
                                          RELIABLE_PACKET,
                                          HCI_PACKET_TYPE,
                                          lenDin );

    crc = 0xFFFF;
    crc = crc16_compute( pdata4, 4     , &crc);
    crc = crc16_compute( pDin  , lenDin, &crc);

    crc01[0] = (uint8_t)( crc & 0xFF);
    crc01[1] = (uint8_t)((crc & 0xFF00) >> 8);
               
    totalLength = 0;

    if( cbOut != 0) cb16_push( cbOut, 0xC0  );
    totalLength += 1;

    for( i=0 ; i<4; i++ )
    {
        len12 = slip_encode_byte( pdata4[i], &b0, &b1 );
        if( cbOut != 0) cb16_push( cbOut, b0 );
        totalLength += 1;
        if(len12 == 2)
        {
            if( cbOut != 0) cb16_push( cbOut, b0 );
            totalLength += 1;
        }
    }

    for( i=0 ; i<lenDin; i++ )
    {
        len12 = slip_encode_byte( pDin[i], &b0, &b1 );
        if( cbOut != 0) cb16_push( cbOut, b0 );
        totalLength += 1;
        if(len12 == 2)
        {
            if( cbOut != 0) cb16_push( cbOut, b0 );
            totalLength += 1;
        }
    }

    for( i=0 ; i<2; i++ )
    {
        len12 = slip_encode_byte( crc01[i], &b0, &b1 );
        if( cbOut != 0) cb16_push( cbOut, b0 );
        totalLength += 1;
        if(len12 == 2)
        {
            if( cbOut != 0) cb16_push( cbOut, b0 );
            totalLength += 1;
        }
    }

    if( cbOut != 0) cb16_push( cbOut, b0 );
    totalLength += 1;

    *plenDout = totalLength;

    return(totalLength);
}
Esempio n. 16
0
void bridge_uart_event_handler(app_uart_evt_t *p_app_uart_event)
{
    uint8_t uart_rx;
  
	  // Check if UART data has been received.
    if(p_app_uart_event->evt_type == APP_UART_DATA_READY)
    {
			  // Getting a byte from the UART.
        if(app_uart_get(&uart_rx) != NRF_SUCCESS)
        {
            return;
        }
        
        switch(bridge.rx.state) 
        {
            static uint8_t   payload_count;
            static uint16_t  crc16;
            
					  // Start of next packet detected.
            case BRIDGE_STATE_COMMAND_WAIT:
            {
                bridge_check_command_rcv((bridge_commands_t)uart_rx);
                break;
            }
            
						// Length byte received.
            case BRIDGE_STATE_LENGTH_WAIT:
            {
                bridge.rx.packet.payload_length = uart_rx;
                payload_count = 0;
                bridge.rx.state = BRIDGE_STATE_PAYLOAD_WAIT;
                break;
            }
            
						// Reading payload.
            case BRIDGE_STATE_PAYLOAD_WAIT:
            {
                
                bridge.rx.packet.payload[payload_count] = uart_rx;
                payload_count++;
                if(payload_count >= bridge.rx.packet.payload_length)
                {
                    bridge.rx.state = BRIDGE_STATE_CRC16_LOW_WAIT;
                }
                
                break;
            }
            
						// Get first crc16 byte.
            case BRIDGE_STATE_CRC16_LOW_WAIT:
            {
                crc16 = uart_rx;
                bridge.rx.state = BRIDGE_STATE_CRC16_HIGH_WAIT;
                break;
            }
            
						// Get second crc16 byte.
            case BRIDGE_STATE_CRC16_HIGH_WAIT:
            {  
                
							  // If device is not connected of notification/indication is not enabled send BRIDGE_COMM_NCONN byte.
                if( !ble_is_device_connected() ||
                    (
                        ((characteristic_sensorData_up_info.state & BLE_CHARACTERISTIC_IS_NOTIFYING)  == 0)&&
                        ((characteristic_sensorData_up_info.state & BLE_CHARACTERISTIC_IS_INDICATING) == 0)
                    ) 
                  )
                {
                    app_uart_put(BRIDGE_COMM_NCONN);
                }  
                else
                {
                    crc16 += ((uint16_t)uart_rx << 8);
                    crc16_1 = crc16_compute((uint8_t *)&bridge.rx.packet, bridge.rx.packet.payload_length + BRIDGE_HEDER_SIZE, NULL);
									  // Compare received crc16 with calculated value.
                    if(
                        (crc16 == crc16_compute((uint8_t *)&bridge.rx.packet, bridge.rx.packet.payload_length + BRIDGE_HEDER_SIZE, NULL)) &&
                        (bridge.rx.packet.payload_length <= BRIDGE_PAYLOAD_SIZE)
                      )
                    {
                        // Send data over ble and ACK over uart.
											  memset((uint8_t*)&sensor_bridge.data_up, 0, sizeof(sensor_bridge.data_up)); 
                        sensor_bridge.data_up.payload_length = bridge.rx.packet.payload_length;
                        memcpy((uint8_t*)&sensor_bridge.data_up.payload, (uint8_t*)&bridge.rx.packet.payload, bridge.rx.packet.payload_length); 
                        ble_update_characteristic_value(&characteristic_sensorData_up_info, (uint8_t *)(&sensor_bridge.data_up), sizeof(sensor_bridge.data_up));
                        app_uart_put(BRIDGE_COMM_ACK);
                    }
										// Send BRIDGE_COMM_NACK byte.
                    else
                    {
                        app_uart_put(BRIDGE_COMM_NACK);
                    }
                }
                
								// Go to BRIDGE_STATE_COMMAND_WAIT state (wait to next packet).
                bridge.rx.state = BRIDGE_STATE_COMMAND_WAIT;
                break;
            }
            
            // ACK wait state. 
            case BRIDGE_STATE_ACK_WAIT:
            {
							  // If ACK received reset resend counter and go to BRIDGE_STATE_COMMAND_WAIT state.
                if(uart_rx == BRIDGE_COMM_ACK)
                {
                    bridge.tx.resend_counter = 0;
                    bridge.rx.state = BRIDGE_STATE_COMMAND_WAIT;
                }
                
								// If NACK received?
                else if(uart_rx == BRIDGE_COMM_NACK)
                {
									  // If there is need to do more resends?
                    if(bridge.tx.resend_counter < NUMBER_OF_RESEND)
                    {
											  // Resend last packet, and increment resend_counter.
                        bridge_send_packet();
                        bridge.tx.resend_counter++;
                    }
                    else
                    {
											  // Reset resend counter and go to BRIDGE_STATE_COMMAND_WAIT state.
                        bridge.tx.resend_counter = 0;
                        bridge.rx.state = BRIDGE_STATE_COMMAND_WAIT;
                    }
                }
								
								// Can be considered to have received the beginning of a new package.
                else
                {
                    bridge_check_command_rcv((bridge_commands_t)uart_rx);
                }
                
                break;
            }
        }
    }
}