📄 wdp_device.c
字号:
/* Copyright (c) 2007 Nordic Semiconductor. All Rights Reserved.
*
* The information contained herein is confidential property of
* Nordic Semiconductor. The use, copying, transfer or disclosure
* of such information is prohibited except by express written
* agreement with Nordic Semiconductor.
*/
/** @file
*
* Device source code for the Wireless Desktop Protocol.
*
* @author Lasse Olsen
*
*/
#include "wdp_device.h"
#include <string.h>
//*****************************************************************************
// Misc. macros
//*****************************************************************************
#define WDP_GET_BIT(a, b) ((a >> b) & 0x01)
#define WDP_CLEAR_BIT(a, b) (a &= ~(1 << b))
#define WDP_SET_BIT(a, b) (a |= (1 << b))
typedef enum
{
WDP_CONNECTED,
WDP_SEND_KEEP_ALIVE
} wdp_status_register;
static xdata uint8_t wdp_status;
static xdata uint16_t wdp_keep_alive_counter;
static xdata fap_tx_rx_struct_t wdp_general_buffer;
static const uint8_t wdp_pairing_ch_tab[FAP_CH_TAB_SIZE] = WDP_PAIRING_CHANNELS;
void wdp_send_keep_alive();
bool wdp_transmit_tx_buffer_and_wait(fap_tx_rx_struct_t *dat, uint16_t max_latency);
typedef struct
{
uint8_t pairing_address[FAP_ADDRESS_WIDTH];
}dev_static_setup_t;
xdata dev_static_setup_t wdp_dev_static_setup =
{
WDP_PAIRING_ADDRESS,
};
typedef struct
{
uint8_t dev_address[FAP_ADDRESS_WIDTH];
wdp_dev_types_t dev_type;
uint16_t ka_interval;
}dev_dynamic_setup_t;
static xdata dev_dynamic_setup_t wdp_dev_dynamic_setup;
void wdp_device_init(wdp_dev_types_t dev_type)
{
fap_init();
WDP_CLEAR_BIT(wdp_status, WDP_CONNECTED);
WDP_CLEAR_BIT(wdp_status, WDP_SEND_KEEP_ALIVE);
fap_set_address(FAP_DEVICE0, wdp_dev_static_setup.pairing_address);
wdp_dev_dynamic_setup.dev_type = dev_type;
switch(dev_type)
{
case WDP_MOUSE:
wdp_dev_dynamic_setup.ka_interval = WDP_MOUSE_KA_INTERVAL;
break;
case WDP_KEYBOARD:
wdp_dev_dynamic_setup.ka_interval = WDP_KEYBOARD_KA_INTERVAL;
break;
case WDP_REMOTE:
wdp_dev_dynamic_setup.ka_interval = WDP_REMOTE_KA_INTERVAL;
break;
default:
break;
}
}
void wdp_device_process_events()
{
if(WDP_GET_BIT(wdp_status, WDP_CONNECTED))
{
if(!fap_tx_success())
{
WDP_CLEAR_BIT(wdp_status, WDP_CONNECTED);
}
if(WDP_GET_BIT(wdp_status, WDP_SEND_KEEP_ALIVE))
{
WDP_CLEAR_BIT(wdp_status, WDP_SEND_KEEP_ALIVE);
wdp_send_keep_alive();
}
}
}
void wdp_timer_isr_function()
{
if(WDP_GET_BIT(wdp_status, WDP_CONNECTED))
{
if(wdp_keep_alive_counter < wdp_dev_dynamic_setup.ka_interval)
{
wdp_keep_alive_counter++;
}
else
{
wdp_keep_alive_counter=0; // Reset keep alive counter
WDP_SET_BIT(wdp_status, WDP_SEND_KEEP_ALIVE);
}
}
}
void wdp_device_connect()
{
WDP_SET_BIT(wdp_status, WDP_CONNECTED);
wdp_send_keep_alive();
}
void wdp_device_disconnect()
{
WDP_CLEAR_BIT(wdp_status, WDP_CONNECTED);
}
bool wdp_device_send_data(uint8_t *dat, uint8_t length)
{
if(length <= WDP_MAX_UL_PL_LENGTH)
{
wdp_general_buffer.pipe = FAP_DEVICE1;
wdp_general_buffer.pl[WDP_TYPE_ID] = USER_DATA;
memcpy(&wdp_general_buffer.pl[WDP_APP_PL_START], dat, length);
wdp_general_buffer.pl_length = (WDP_APP_PL_START + length);
wdp_keep_alive_counter=0;
return fap_tx_data(&wdp_general_buffer, WDP_TX_DATA_TIMEOUT);
}
else
{
return false;
}
}
bool wdp_device_get_downlink_data(uint8_t *dst, uint8_t *length)
{
if(fap_read_rx_fifo(&wdp_general_buffer))
{
memcpy(dst, &wdp_general_buffer.pl[0], wdp_general_buffer.pl_length);
*length = wdp_general_buffer.pl_length;
return true;
}
else
{
return false;
}
}
bool wdp_device_request_pairing()
{
fap_goto_idle_mode();
fap_set_channels(wdp_pairing_ch_tab);
fap_set_output_power(WDP_PAIRING_OUTPUT_POWER);
wdp_general_buffer.pl[WDP_TYPE_ID] = PAIRING_REQ;
wdp_general_buffer.pl[DEV_TYPE] = wdp_dev_dynamic_setup.dev_type;
wdp_general_buffer.pipe = WDP_PAIRING_PIPE;
wdp_general_buffer.pl_length = WDP_PAIRING_PL_LENGTH;
wdp_transmit_tx_buffer_and_wait(&wdp_general_buffer, WDP_TX_PAIRING_TIMEOUT);
fap_flush_rx_fifo();
if(wdp_transmit_tx_buffer_and_wait(&wdp_general_buffer, WDP_TX_PAIRING_TIMEOUT))
{
if(fap_read_rx_fifo(&wdp_general_buffer))
{
if(wdp_general_buffer.pl[WDP_TYPE_ID] == PAIRING_RESP &&
wdp_general_buffer.pl[DEV_TYPE] == wdp_dev_dynamic_setup.dev_type)
{
fap_set_address(FAP_DEVICE1, &wdp_general_buffer.pl[ADDRESS_B0]);
wdp_general_buffer.pl[WDP_TYPE_ID] = PAIRING_COMPL; // Pairing complete
wdp_general_buffer.pipe = WDP_PAIRING_PIPE;
wdp_general_buffer.pl_length = WDP_PAIRING_PL_LENGTH;
if(wdp_transmit_tx_buffer_and_wait(&wdp_general_buffer, WDP_TX_PAIRING_TIMEOUT))
{
fap_flush_rx_fifo();
fap_get_address(FAP_DEVICE1, &wdp_general_buffer.pl[0]);
wdp_extract_channels(wdp_general_buffer.pl[1], &wdp_general_buffer.pl[0]);
fap_set_channels(&wdp_general_buffer.pl[0]);
fap_set_output_power(FAP_OUTPUT_POWER);
return true;
}
}
}
}
fap_flush_rx_fifo();
fap_get_address(FAP_DEVICE1, &wdp_general_buffer.pl[0]);
wdp_extract_channels(wdp_general_buffer.pl[1], &wdp_general_buffer.pl[0]);
fap_set_channels(&wdp_general_buffer.pl[0]);
fap_set_output_power(FAP_OUTPUT_POWER);
return false;
}
void wdp_device_set_address(uint8_t *adr)
{
fap_set_address(FAP_DEVICE1, adr);
wdp_extract_channels(adr[1], &wdp_general_buffer.pl[0]);
fap_set_channels(&wdp_general_buffer.pl[0]);
}
bool wdp_device_connected(void)
{
return WDP_GET_BIT(wdp_status, WDP_CONNECTED);
}
// Internal
bool wdp_transmit_tx_buffer_and_wait(fap_tx_rx_struct_t *datainput, uint16_t tx_timeout)
{
wdp_keep_alive_counter=0; // Reset keep-alive counter whenever data transmitted
fap_tx_data(datainput, tx_timeout); // Send packet
while(fap_get_mode()!= FAP_IDLE); // Wait until finished
if(fap_tx_success())
{
return true;
}
else
{
return false;
}
}
void wdp_send_keep_alive()
{
wdp_general_buffer.pl[WDP_TYPE_ID] = KEEP_ALIVE;
wdp_general_buffer.pipe = FAP_DEVICE1;
wdp_general_buffer.pl_length = WDP_TYPE_ID_ONLY_PL;
if(fap_get_mode() == FAP_IDLE)
{
fap_tx_data(&wdp_general_buffer, WDP_TX_DATA_TIMEOUT); // Send packet
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -