📄 protocol.c
字号:
if(( rx_packet.bind_request.hdr.type == BIND_REQ ) && (rx_data_length == BIND_REQ_LEN))
{
// If successfully transmitted
if(RadioSendPacket( BIND_RESP_RETRIES, BIND_RESP_LEN ))
{
#ifdef ENCRYPT_TEA
// Check for keyboard device
if( rx_packet.bind_request.hdr.dev_type == KEYBOARD_DEVICE_TYPE)
GenerateEncryptKey();
#endif // ENCRYPT_TEA
break;
}
} // BIND_REQ
bind_channel += 6;
if (bind_channel >= NUM_CHANNELS)
{
bind_channel -= NUM_CHANNELS;
}
retry_count--;
if((retry_count & 0x0007) == 0x0004) //200ms duty circle
NotifyContinueBind();
} // while( retry_count )
NotifyStopBind();
// Set CRC
RadioSetNonzeroCrcSeed();
// Restore PA Level
RadioSetPa( DATA_MODE_PA );
MasterProtocolPingMode(PING_REASON_NORMAL);
}
#ifdef KISS_BIND
///////////////////////////////////////////////////////////////////////////////
//
// Function: MasterProtocolUnbind
//
//! Description: Unbind the device from the bridge by clear the bind flag.
//!
//! Inputs: Void
//!
//! Returns: Void
//!
///////////////////////////////////////////////////////////////////////////////
void MasterProtocolUnbind(void)
{
sys_params.device_bound.signature = BIND_SIGNATURE;
sys_params.device_bound.bound_flg = 0;
StoreSystemParameters();
}
#endif //KISS_BIND
///////////////////////////////////////////////////////////////////////////////
//
// Function: MasterProtocolDataMode
//
//! Description: The bridge continuously listen for DATA packets from the HID.
//! When valid data is received from the HID the bridge sends an
//! ACK to the HID and sends the data to the USB host. If invalid
//! data is received the bridge will ignore the packet and listen
//! for the HID to retransmit the data. The bridge monitors the
//! interference level and will move to Ping Mode if the defined
//! interference threshold is reached. This ensures that the bridge
//! is operating on a clean channel.
//!
//! Inputs: Void
//!
//! Returns: Void
//!
///////////////////////////////////////////////////////////////////////////////
void MasterProtocolDataMode( void )
{
unsigned char status;
status = RadioGetReceiveState();
if ((status & (RADIO_ERROR | RADIO_COMPLETE)) == RADIO_COMPLETE)
{
if( total_received_packet_count < 0xFFFF )
total_received_packet_count++;
local_total_received_packet_count++;
if( local_total_received_packet_count == 0 )
{
local_bad_received_packet_count = 0;
}
rx_data_length = RadioEndReceive();
MasterProtocolProcessPacket();
RadioStartReceivePacket();
TimerSetTimer(QUICK_RSSI_TIMEOUT);
}
else if (status & RADIO_ERROR)
{
if( bad_received_packet_count< 0xFFFF )
bad_received_packet_count++;
(void)RadioEndReceive();
if( local_bad_received_packet_count < 0xFF )
local_bad_received_packet_count++;
local_total_received_packet_count++;
if( local_total_received_packet_count == 0 )
{
local_bad_received_packet_count = 0;
}
if(local_total_received_packet_count >= 16 &&
(local_total_received_packet_count>>2) > (local_total_received_packet_count-local_bad_received_packet_count)) //good packet less than 25%
{
local_total_received_packet_count = 0;
local_bad_received_packet_count = 0;
// need to go to ping mode
MasterProtocolPingMode(PING_REASON_CORRUPT);
}
else
RadioStartReceivePacket();
}
// Check the RSSI
else
{
// Check if the LP is still alive
// Read PWR_CTRL_ADR register, it should be ZERO for Bridge
if(RadioRead(PWR_CTRL_ADR)!= 0)
MasterProtocolInit();
// need to check RSSI 2 ms after starting receive, or after a packet..
else if (TimerTimeOut())
{
if (MasterProtocolCheckRssi() > RSSI_NOISE_THRESHOLD)
{
if (rssi_counter > NUM_HIGH_RSSI_READINGS)
{
rx_data_length = RadioAbort();
if (rx_data_length != RADIO_ABORT_SUCCESS)
MasterProtocolProcessPacket();
// need to go to ping mode
MasterProtocolPingMode(PING_REASON_RSSI);
}
}
TimerSetTimer(QUICK_RSSI_TIMEOUT);
}
}
}
///////////////////////////////////////////////////////////////////////////////
//
// Function: MasterProtocolProcessPacket
//
//! Description: Process the receiving packet. First, it checks for data packet.
//! Second it checks if the packet is a connect request with an approved
//! device or if it is a ping packet.
//!
//! Inputs: Void
//!
//! Returns: Void
//!
///////////////////////////////////////////////////////////////////////////////
static void MasterProtocolProcessPacket( void )
{
#ifdef ENCRYPT_AES
if (rx_data_length == 16) //must be AES
{
unsigned char i;
// Decrypt Report
AES_Decrypt();
// Determine valid length
for( i = rx_data_length; i > 0x0; i-- )
{
// Ignore fill random data
if( rx_packet.encrypt_aes.payload[i-1] == 0x0 )
{
rx_data_length = i-1;
break;
}
}
if( i > 0 && rx_data_length >1)
{
// Swap device type bit0 and bit1
rx_packet.data.hdr.data_dev_type = data_dev_type_swap_table[rx_packet.data.hdr.data_dev_type];
if(rx_packet.data.hdr.dt_data == !!(device_data_toggle & MasterProtocolDeviceTypeToBit( rx_packet.data.hdr.data_dev_type)))
{
if((report_handler[rx_packet.data.hdr.data_dev_type])());
{
device_data_toggle ^= MasterProtocolDeviceTypeToBit( rx_packet.data.hdr.data_dev_type);
}
}
}
}
else
#endif //ENCRYPT_AES
if( rx_packet.data.hdr.type == DATA_PACKET )
{
// Swap device type bit0 and bit1
rx_packet.data.hdr.data_dev_type = data_dev_type_swap_table[rx_packet.data.hdr.data_dev_type];
if(rx_packet.data.hdr.dt_data == !!(device_data_toggle & MasterProtocolDeviceTypeToBit( rx_packet.data.hdr.data_dev_type)))
{
if((report_handler[rx_packet.data.hdr.data_dev_type])());
{
device_data_toggle ^= MasterProtocolDeviceTypeToBit( rx_packet.data.hdr.data_dev_type);
}
}
#ifdef BACK_CHANNEL_SUPPORT
if( rx_packet.data.hdr.back_ch_req )
{
unsigned char ii;
RadioSetBackChannelCrcSeed();
// setup for a Back Channel Packet and bump the data toggle
tx_packet.first.byte = 0; // clear the header byte
tx_packet.data.hdr.type = BACK_CHANNEL_PACKET;
tx_packet.data.hdr.data_dev_type = data_dev_type_swap_table[rx_packet.data.hdr.data_dev_type];
tx_packet.data.hdr.dt_data = tx_data_toggle;
//Load back channel data to transmit buffer.
for (ii = 0; ii<BACK_CHANNEL_PAYLOAD_LEN; ii++)
tx_packet.data.payload[ii] = back_channel_buffer[ii];
if( RadioSendPacket( BACK_CHANNEL_PACKET_RETRIES, BACK_CHANNEL_PAYLOAD_LEN +1 ) )
{
tx_data_toggle ^= 1;
}
//return to system CRC
RadioSetNonzeroCrcSeed();
}
#endif //BACK_CHANNEL_SUPPORT
}
// check for an "approved" device trying to connect
else if(( rx_packet.connect_request.hdr.type == CONNECT_REQ ) && (rx_data_length >= CONNECT_REQ_LEN))
{
// save the connect data and reply
if( (sys_params.bridge_mid.mid_1 == rx_packet.connect_request.mid_1) &&
(sys_params.bridge_mid.mid_2 == rx_packet.connect_request.mid_2) &&
(sys_params.bridge_mid.mid_3 == rx_packet.connect_request.mid_3) &&
(sys_params.bridge_mid.mid_4 == rx_packet.connect_request.mid_4) )
{
#ifdef KISS_BIND
// Read the bound device flag
RetrieveSystemParameters();
if(!(sys_params.device_bound.bound_flg & MasterProtocolDeviceTypeToBit(rx_packet.connect_request.hdr.dev_type)))
{
sys_params.device_bound.signature = BIND_SIGNATURE;
sys_params.device_bound.bound_flg |= MasterProtocolDeviceTypeToBit(rx_packet.connect_request.hdr.dev_type);
StoreSystemParameters();
}
#endif //KISS_BIND
// Send a Connect response
// format the connect response packet
tx_packet.first.byte = 0; // clear the packet
tx_packet.connect_response.hdr.type = CONNECT_RESP;
tx_packet.connect_response.hdr.flag = 1;
// send the response
RadioSendPacket(CONNECT_RESP_RETRIES, CONNECT_RESP_LEN );
}
}
// check for ping requests from a bridge
else if(( rx_packet.first.byte == (PING_PACKET<<4 | PING_REQ) ) && (rx_data_length == PING_LEN))
{
// Format Ping Response packet
tx_packet.first.byte = (PING_PACKET<<4 | PING_RESP); // 0x31
RadioSetCrcSeed(0);
// Send Ping Response
RadioSendPacket(PING_RESP_RETRIES, PING_LEN);
// Set CRC
RadioSetNonzeroCrcSeed();
}
#ifdef KISS_BIND
else if ((rx_packet.bind_request.hdr.type == KISS_BIND_REQ) && (rx_data_length == KISS_BIND_REQ_LEN))
{
#if (defined RSSI_QUALIFY && defined PROMISCUOUS_MODE)
if(RadioGetRxRssi() >= KISS_BIND_RSSI_THRESHOLD) // The pheripheral is close to the bridge
#endif //defined RSSI_QUALIFY && defined PROMISCUOUS_MODE
{
// Send a Bind response
// format the bind response packet
tx_packet.first.byte = 0; // clear the packet
tx_packet.bind_response.hdr.type = KISS_BIND_RESP;
tx_packet.bind_response.hdr.dev_type = rx_packet.bind_request.hdr.dev_type;
tx_packet.bind_response.mid_1 = sys_params.bridge_mid.mid_1;
tx_packet.bind_response.mid_2 = sys_params.bridge_mid.mid_2;
tx_packet.bind_response.mid_3 = sys_params.bridge_mid.mid_3;
tx_packet.bind_response.mid_4 = sys_params.bridge_mid.mid_4;
// Set PA Level
RadioSetPa( KISS_BIND_PA );
// Set Zero CRC
RadioSetCrcSeed(0);
#ifndef PROMISCUOUS_MODE
// Read the bound device flag
RetrieveSystemParameters();
if(!( sys_params.device_bound.bound_flg & MasterProtocolDeviceTypeToBit( rx_packet.bind_request.hdr.dev_type)))
#endif //PROMISCUOUS_MODE
{
#ifdef ENCRYPT_TEA
// Check for keyboard device
if( rx_packet.bind_request.hdr.dev_type == KEYBOARD_DEVICE_TYPE)
GenerateEncryptKey();
#endif // ENCRYPT_TEA
RadioSendPacket(KISS_BIND_RESP_RETRIES, BIND_RESP_LEN );
}
// Set CRC
RadioSetNonzeroCrcSeed();
// Restore PA Level
RadioSetPa( DATA_MODE_PA );
}
}
#endif //KISS_BIND
#ifdef ENCRYPT_TEA
else if( (rx_packet.data.hdr.type == ENCRYPT_KEY_REQ) && (rx_data_length == ENCRYPT_KEY_REQUEST_LEN) )
{
// Reduce PA
RadioSetPa( ENCRYPT_KEY_PA );
// Retrieve encrypt key from flash
RetrieveSystemParameters();
// Check which half of key
if( rx_packet.encrypt.header == KEY_REQUEST_FIRST_SECTION )
{
// Encrypt session key with common key
rx_packet.encrypt.payload[0] = sys_params.encrypt_key.block.key[0];
rx_packet.encrypt.payload[1] = sys_params.encrypt_key.block.key[1];
// First half
tx_packet.encrypt.header = KEY_RESPONSE_FIRST_SECTION;
}
else
{
// Encrypt session key with common key
rx_packet.encrypt.payload[0] = sys_params.encrypt_key.block.key[2];
rx_packet.encrypt.payload[1] = sys_params.encrypt_key.block.key[3];
// Second half
tx_packet.encrypt.header = KEY_RESPONSE_LAST_SECTION;
}
EncryptKey();
tx_packet.encrypt.payload[0] = rx_packet.encrypt.payload[0];
tx_packet.encrypt.payload[1] = rx_packet.encrypt.payload[1];
// send the response
RadioSendPacket(ENCRYPT_KEY_RESP_RETRIES, ENCRYPT_KEY_RESPONSE_LEN );
// Restore PA Level
RadioSetPa( DATA_MODE_PA );
}
#endif // ENCRYPT_TEA
}
///////////////////////////////////////////////////////////////////////////////
//
// Function: MasterProtocolCheckRssi
//
//! Description: Check the channel noise level.
//!
//! Inputs: Void
//!
//! Returns:
//! - rssi - rssi value
//!
///////////////////////////////////////////////////////////////////////////////
static unsigned char MasterProtocolCheckRssi(void)
{
unsigned char rssi;
// read RSSI
rssi = MasterProtocolGetNoiseRssi();
if (rssi > RSSI_NOISE_THRESHOLD)
{
rssi_counter++;
}
else
{
rssi_counter = 0;
}
return rssi;
}
///////////////////////////////////////////////////////////////////////////////
//
// Function: MasterProtocolGetNoiseRssi
//
//! Description: Get RSSI for non-trasmission (noise)
//!
//!
//! Inputs: Void
//!
//! Returns: RSSI value
//!
///////////////////////////////////////////////////////////////////////////////
static unsigned char MasterProtocolGetNoiseRssi(void)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -