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

📄 protocol.c

📁 Cypress公司开发的2.4G无线键盘鼠标及其Bridge源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
//--------------------------------------------------------------------------
//
//  Filename:     protocol.c
//
//! \file
//!
//! Collection of protocol and bind prototypes.
//!
//--------------------------------------------------------------------------
// WirelessUSB LP Protocol Version 2.1
//--------------------------------------------------------------------------
//
// Copyright 2003-2006, Cypress Semiconductor Corporation.
//
// This software is owned by Cypress Semiconductor Corporation (Cypress)
// and is protected by and subject to worldwide patent protection (United
// States and foreign), United States copyright laws and international 
// treaty provisions. Cypress hereby grants to licensee a personal, 
// non-exclusive, non-transferable license to copy, use, modify, create 
// derivative works of, and compile the Cypress Source Code and derivative 
// works for the sole purpose of creating custom software in support of 
// licensee product to be used only in conjunction with a Cypress integrated 
// circuit as specified in the applicable agreement. Any reproduction, 
// modification, translation, compilation, or representation of this 
// software except as specified above is prohibited without the express 
// written permission of Cypress.
//
// Disclaimer: CYPRESS MAKES NO WARRANTY OF ANY KIND,EXPRESS OR IMPLIED, 
// WITH REGARD TO THIS MATERIAL, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
// Cypress reserves the right to make changes without further notice to the
// materials described herein. Cypress does not assume any liability arising
// out of the application or use of any product or circuit described herein.
// Cypress does not authorize its products for use as critical components in
// life-support systems where a malfunction or failure may reasonably be
// expected to result in significant injury to the user. The inclusion of
// Cypress' product in a life-support systems application implies that the
// manufacturer assumes all risk of such use and in doing so indemnifies
// Cypress against all charges.
//
// Use may be limited by and subject to the applicable Cypress software
// license agreement.
//
//--------------------------------------------------------------------------

//--------------------------------------
// Included files
//--------------------------------------


#include "protocol.h"
#include "lpradio.h"

//--------------------------------------
// External API to be implemented by customer
//--------------------------------------
extern void NotifyStartBind(void);
extern void NotifyContinueBind(void);
extern void NotifyStopBind(void);
extern void NotifyStartPing(void);
extern void NotifyStopPing(void);
extern unsigned char handle_mouse_report(void);
extern unsigned char handle_keyboard_report(void);
extern void RetrieveSystemParameters(void);
extern void StoreSystemParameters(void);
extern void TimerDelay10usec(void);
extern void TimerDelay50usec(void);
extern void TimerDelay100usec(void);
extern void TxRetryDelay(void);
extern void TimerSetTimer(unsigned char timeout_ms);
extern unsigned char TimerTimeOut(void);
extern void TimerDelayMsec(unsigned short num_milliseconds);
extern void DecryptData(void);
extern void AES_Decrypt(void);
extern void GenerateEncryptKey(void);
extern void EncryptKey(void);
extern unsigned char EncryptRequestKey(void);
extern void EncryptData(unsigned char data_length);

extern void NotifyDownloadBackChannelData(void);


//--------------------------------------
// Local Function Declarations
//--------------------------------------

static void  RadioCalculateNetworkId(void);
static void  RadioGetNextChannel(void);
static void RadioSetPa(unsigned char pa);
static void RadioSetNonzeroCrcSeed(void);
static unsigned char RadioGetRxRssi(void);
static void MasterProtocolProcessPacket( void );
static unsigned char MasterProtocolCheckRssi(void);
static unsigned char MasterProtocolGetNoiseRssi(void);
static unsigned char MasterProtocolDeviceTypeToBit(unsigned char dev_type);
static void RadioSetBackChannelCrcSeed(void);
static void SlaveProtocolRetrieveBridgeMid(void);
static void SlaveProtocolKissBind(unsigned char dev_type);


//--------------------------------------
// Local Global Definitions
//--------------------------------------
extern unsigned char RadioXactConfig;

//--------------------------------------
// Local Variable Definitions
//--------------------------------------

// System parameters
SYS_PARAMETERS sys_params;

//! Receive packet
LP_PACKET      rx_packet;

//! Transmit packet
LP_PACKET      tx_packet;

const unsigned char data_dev_type_swap_table[4] = {0, 2, 1, 3};

#ifdef MASTER_PROTOCOL
    //! Receive data toggle
    // bit0 - for device type 0
    // bit1 - for device type 1
    // bit2 - for device type 2 
    // bit3 - for device type 3
    unsigned char device_data_toggle;  

    //! Data length for receive data
    unsigned char rx_data_length;
    
    //! Receive signal strength indicator counter
    unsigned char  rssi_counter = 0;
    
    //! Total Received Packet Count
    unsigned short total_received_packet_count = 0;
    unsigned char local_total_received_packet_count = 0;
    
    //! Bad Received Packet Count
    unsigned short bad_received_packet_count = 0;
    unsigned char local_bad_received_packet_count = 0;
    
    #ifdef BACK_CHANNEL_SUPPORT
    unsigned char tx_data_toggle = 1;
    #endif //BACK_CHANNEL_SUPPORT

    unsigned char back_channel_buffer[BACK_CHANNEL_PAYLOAD_LEN];      

    typedef unsigned char (*fptr)(void);
    const fptr report_handler[4]=
    {
        handle_keyboard_report,            // Device type 0, Presenter
        handle_mouse_report,               // Device type 1, Undefined Device
        handle_keyboard_report,            // Device type 2, Keyboard
        handle_mouse_report,               // Device type 3, Mouse 
    };

#else // MASTER_PROTOCOL
    // Protocol connected state
    PROTOCOL_CONNECT_STATE connected_state;
    
    // Transmit packet data toggle
    unsigned char tx_data_toggle = 1;  

    #ifdef ENCRYPT_TEA
    unsigned char encrypt_key_received;
    #endif //ENCRYPT_TEA

    #ifdef BACK_CHANNEL_SUPPORT
    unsigned char rx_data_length;
    unsigned char rx_data_toggle = 1;
    #endif //BACK_CHANNEL_SUPPORT

#endif // MASTER_PROTOCOL




//--------------------------------------
// Local Function Declarations
//--------------------------------------

#ifdef MASTER_PROTOCOL
//*****************************************************************************
//*****************************************************************************
//
// *******************  For Master Protocol ***********************************
//
//*****************************************************************************
//*****************************************************************************


///////////////////////////////////////////////////////////////////////////////
//
//   Function:    MasterProtocolInit
//
//!  Description: Calls radio init, and figures device parameters using 
//!               algorithms to find PN code, channel, pin, and CRC seed  
//!               (based off the MID).  The data toggles gets set. 
//!               Then makes sure a channel is found at startup.
//!
//!  Inputs:      Void
//!
//!  Returns:     Void
//!
///////////////////////////////////////////////////////////////////////////////

void MasterProtocolInit(void)
{
    unsigned char temp[6]; 

    // Configure the Radio
    RadioInit(ACK_EN|END_STATE_RX|ACK_TO_8X, DATA_MODE_PA|DATCODE_LEN_32|DATMODE_8DR);
    
    // Configure the frame
    RadioSetFrameConfig(SOP_EN|LEN_EN|4);
    
    // Load the Preamble with 0x01
    // This design defaults to using 16-chip Preamble. The 16 chip Preamble sequence 
    // may be repeated multiple times (see Register PREAMBLE_ADR). The longer 
    // Preamble allows the receiver amble time to "lock" to the coming signal. Our 
    // testing shows that 16-chip sequence is sufficient.
    
    RadioSetPreambleCount(0x01);
    
    // Disable PMU  
    RadioWrite(PWR_CTRL_ADR, 0); 
    

    // Retrieve the bridge MID
    // Set receive length
    RadioSetLength(sizeof(rx_packet));
    // Set buffer pointer
    RadioSetPtr(temp);
    // Get MID
    RadioGetFuses();

    sys_params.bridge_mid.mid_1 = temp[0];
    sys_params.bridge_mid.mid_2 = temp[1];
    sys_params.bridge_mid.mid_3 = temp[2];
    sys_params.bridge_mid.mid_4 = temp[3];

    // hash out values for PN Code, Base Channel, and Network 
    // PIN using the same algorithm as all devices
    RadioCalculateNetworkId();
    
    // Initialize device data toggles
    device_data_toggle = 0xFF;

    TimerSetTimer(QUICK_RSSI_TIMEOUT);
    

#ifdef POWER_BIND    
    // Support two devices
    MasterProtocolButtonBindMode(MASTER_POWER_BIND_RETRY_COUNT);
    MasterProtocolButtonBindMode(MASTER_POWER_BIND_RETRY_COUNT);
#else
    // always find a channel on startup
    MasterProtocolPingMode(PING_REASON_NORMAL);
#endif //POWER_BIND


#if ( defined ENCRYPT_TEA || defined KISS_BIND) 
    RetrieveSystemParameters();
#endif //( defined ENCRYPT_TEA || defined KISS_BIND)

#ifdef KISS_BIND    
    // check for uninitialized flash
    if (sys_params.device_bound.signature != BIND_SIGNATURE &&
        sys_params.device_bound.bound_flg != 0)
    {
        MasterProtocolUnbind();
    }
#endif //KISS_BIND
}

///////////////////////////////////////////////////////////////////////////////
//
//   Function:    MasterProtocolPingMode
//
//!  Description: The bridge first transmits Pings and listens for Ping Responses 
//!               for a defined period of time. During Ping Mode the bridge also 
//!               checks the Receive Signal Strength Indicator (RSSI) of the radio 
//!               in order to determine if a non-WirelessUSB device is using this 
//!               channel (or a WirelessUSB device on the same channel using a 
//!               different PN code). If a Ping Response is received, indicating 
//!               that another bridge is using this channel the bridge will select 
//!               the next channel using the Channel Selection Algorithm and repeat 
//!               this procedure. The bridge will also select another channel using 
//!               the Channel Selection Algorithm if the RSSI is high, which 
//!               indicates that there is other RF sources on the channel. If a Ping 
//!               Response is not received and the RSSI is low, the bridge assumes 
//!               the channel is available and moves to Data Mode.
//!
//!  Inputs:      
//!               - reason - to check if we need to start with the top channel
//!
//!  Returns:     Void
//!
///////////////////////////////////////////////////////////////////////////////

void MasterProtocolPingMode(unsigned char reason)
{
    unsigned char  ping_channel_count = 0;
    unsigned char  rssi_threshold = PING_RSSI_NOISE_THRESHOLD;
    unsigned char  ping_count = 0;
   
    // Ping Operation

    // set the channel and listen for activity, select another channel
    // if the channel is taken  
 
    // use a ping request to find another bridge on the channel, also
    // check for other device/bridge "activity" on the channel
       
    // format the ping packet
    tx_packet.first.byte      = (PING_PACKET<<4 | PING_REQ); // 0x30

    NotifyStartPing();

    if (reason == PING_REASON_NORMAL)
    {
        // Initialize the channel selection algorithm to the top channel
        // in the channel subset
        while (sys_params.network_id.channel < NUM_CHANNELS - 6) 
        {
            sys_params.network_id.channel += 6;
        }
    }
    else
    {
        // get next channel
        RadioGetNextChannel();
    }

    RadioSetCrcSeed(0);
        
    RadioSetSopPnCode(sys_params.network_id.pn_code);

    // send a ping request and wait for response, if no response change
    // the channel and try again

    while ( ping_count < PING_NUM_RSSI )
    {
        //Clear Watchdog and Sleep
        M8C_ClearWDTAndSleep;

        ping_count++;
                
        RadioSetChannel(sys_params.network_id.channel);
        
        // Send PING_REQ packet
        if (RadioSendPacket(PING_REQ_RETRIES, PING_LEN))
        {
            rx_data_length = RadioReceivePacket();

            // Check for Bridge (PING_RESP packet)
            if( (rx_data_length == PING_LEN) && (rx_packet.first.byte == (PING_PACKET<<4 | PING_RESP)) )
            {
                #ifndef PING_NO_HOP 
                RadioGetNextChannel();
                ping_channel_count++;
                ping_count = 0;
                #endif
            }
        }
        else 
        {
            // check RSSI
            if (MasterProtocolGetNoiseRssi() > rssi_threshold)
            {
                RadioGetNextChannel();
                ping_channel_count++;
                ping_count = 0;
            }
        }
        if (ping_channel_count > NUM_CHANNELS_PER_SUBSET)
        {
            if ( rssi_threshold < RSSI_LVL_MSK)
                rssi_threshold++;
            rssi_threshold &= RSSI_LVL_MSK;        
            ping_channel_count = 0;
        }
    }    // while (ping_count < PING_NUM_RSSI)

    NotifyStopPing();

    rssi_counter = 0;

    RadioSetNonzeroCrcSeed();

    RadioStartReceivePacket();
}

///////////////////////////////////////////////////////////////////////////////
//
//  Function:    MasterProtocolButtonBindMode
//
//!  Description: The bridge sets the current channel and PN code to the channel 
//!               and PN code specified in the Bind ID. The bridge listens for 
//!               a Bind Request on each channel for a certain time before selecting 
//!               the next channel. If the bridge receives a Bind Request from the 
//!               HID containing a supported device type, it sends a Bind Response 
//!               containing the bridge抯 Manufacturing ID and then switches to 
//!               Ping Mode. The bridge also switches to Ping Mode if the defined 
//!               time period has elapsed while in Bind Mode. 
//!
//!  Inputs:      Void
//!
//!  Returns:     Void
//!
///////////////////////////////////////////////////////////////////////////////

void MasterProtocolButtonBindMode(unsigned short retry_count)
{
    unsigned char  bind_channel = BIND_BASE_CHANNEL;
        
    NotifyStartBind();
    
    // Abort the previous receiving
    (void)RadioAbort();

    // load the bind pn_code index
    RadioSetSopPnCode(BIND_PN_CODE);

    // Set PA Level
    RadioSetPa( BUTTON_BIND_PA );

    // Set Zero CRC
    RadioSetCrcSeed(0);
    
    // format the bind response packet
    tx_packet.first.byte         = 0;   // clear the packet
    tx_packet.bind_response.hdr.type   = BIND_RESP; 


    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;

    while(retry_count)
    {      
        RadioSetChannel(bind_channel);
 
        // spin until timeout or packet received
        rx_data_length = RadioReceivePacket();

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -