⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 protocol.c

📁 Cypress公司开发的2.4G无线键盘鼠标及其Bridge源代码
💻 C
📖 第 1 页 / 共 4 页
字号:

        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 + -