📄 protocol.c
字号:
//--------------------------------------------------------------------------
//
// 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 + -