📄 main.c
字号:
/****************************************************************************
Copyright (C) Cambridge Silicon Radio 2002
FILE
main.c - keyboard example using HIDEngine
MODIFICATION HISTORY
*****************************************************************************/
#include <stdlib.h>
#include <string.h>
#include <debounce.h>
#include <event.h>
#include <message.h>
#include <sched.h>
#include <vm.h>
#include <ps.h>
#include <timer.h>
#include <pio.h>
#include <hid.h>
#include "keyboard.h"
#include "power_table.h"
#include "hid_keyboard_service_record.h"
/*
Globals
*/
DEVICE_STATE_T dev_state;
/*
Prototypes for static functions
*/
static void initialise(void);
Delay DiscoverableLEDFlasher(TimerHandle h);
/*
Entry point
*/
int main(void)
{
/* initialise our HID */
initialise();
/* Start scheduler as this is event driven.
The first event we should receive is HID_INIT_CFM. */
Sched();
return 0;
}
/*
This function initialises the keyboard by initialising the HID library
and setting internal state.
*/
static void initialise(void)
{
/* create initialisation message to HID library */
MAKE_MSG(HID_INIT_REQ);
/* set up hid service record */
msg->hid_service_record_size = sizeof(hid_keyboard_service_record);
msg->hid_service_record = hid_keyboard_service_record;
/* we don't have a Plug and Play record, but could add one using the same method as for hid record. */
msg->pnp_service_record_size = 0;
/* set class of device to keyboard */
msg->class_of_device = COD_LIMITED_DISCOVERY | HIDCOD_MAJOR | HIDCOD_MINOR_KEYBOARD;
/* define our keyboard interface */
msg->interface = hidio;
msg->sensor_type = uart;
/* We want to enter PIN on our keyboard.
Note that we must include the Pin entry report (ReportID 255).
In the ReportDescriptor in the SDP record. */
msg->keyboard_pin_entry = TRUE;
/* we want to carry on working with Hosts that allow
authentication to be cancelled after failed attempt. */
msg->discard_events_after_authentication_fail = FALSE;
/* send our power management table */
msg->power_state_table = PowerTable;
/* post message to HID library */
MessagePut(0,msg);
/* initialise our info */
memset(&dev_state,0,sizeof(DEVICE_STATE_T));
dev_state.state = init;
/* default protocol is report */
dev_state.protocol = HIDPROTOCOL_REPORT;
/* see if we are virtually cabled - non zero BD addr */
(void)PsRetrieve(0,&dev_state.host_addr,sizeof(BD_ADDR_T));
if (dev_state.host_addr.lap || dev_state.host_addr.nap || dev_state.host_addr.uap)
dev_state.virtual_cable = TRUE;
else
dev_state.virtual_cable = FALSE;
/* set up event on connect button press */
SchedPioEntryChanged();
/* set up output PIOs */
PioSetDir(NUM_LOCK | CAPS_LOCK | SCROLL_LOCK | IDLE_MODE, NUM_LOCK | CAPS_LOCK | SCROLL_LOCK | IDLE_MODE);
/* turn off LEDs and disable IDLE mode */
PioSet(NUM_LOCK | CAPS_LOCK | SCROLL_LOCK | IDLE_MODE, 0);
}
/*
This function starts a connection scenario by sending
CONNECT_REQ to HIDEngine with correct parameters for
type of scenario.
*/
void connect(connect_type_t con_type)
{
MAKE_MSG(HID_CONNECT_REQ);
/* specify our configuration for each connect scenario */
switch (con_type)
{
case reconnect_to_host_on_data:
/* do not poll external micro when disconnected, it should use an Asynchronous Data Transfer to wake up. */
msg->sample_rate = 0;
/*lint -fallthrough */
case reconnect_to_host:
dev_state.state = connecting;
msg->host_addr = dev_state.host_addr;
break;
case host_to_reconnect:
dev_state.state = connecting;
msg->host_addr = dev_state.host_addr;
msg->timeout = 0; /* never timeout */
break;
case host_to_discover_and_connect:
dev_state.state = discoverable;
memset(&msg->host_addr,0,sizeof(BD_ADDR_T));
msg->timeout = 120; /* discoverable for 2 minutes */
/* cancel any existing timer */
TimerCancelCallback(DiscoverableLEDFlasher);
/* start discoverable mode LED flashing now. */
(void)TimerAdd(D_mSEC(2),DiscoverableLEDFlasher);
break;
case reserved1:
case reserved2:
case reconnect_on_data_or_from_host:
default:
}
msg->connect_type = con_type;
/* set the supervision timeout to the same as the SDP record (5 seconds) */
msg->supervision_timeout = 0x1f40;
MessagePut(0,msg);
}
/*
Tell HIDEngine we want the current connection scenario
to fail as soon as possible.
The result will be a CONNECT_CFM as soon as possible reporting
that the scenario had failed or timed out, as in normal operation.
*/
void cancelConnect(void)
{
MAKE_MSG(HID_CANCEL_CONNECT_REQ);
MessagePut(0,msg);
}
/*
Disconnect from the Host.
If the unplug flag is set, we will unplug our virtual cable as
well as disconnecting.
*/
void disconnect(bool_t unplug)
{
MAKE_MSG(HID_DISCONNECT_REQ);
/* set state to disconnecting */
dev_state.state = disconnecting;
/* are we unplugging? */
if (unplug)
{
/* yes remove virtual cable */
removeVirtualCable();
/* tell HIDEngine to unplug */
msg->virtual_cable_unplug = TRUE;
}
else
msg->virtual_cable_unplug = FALSE;
/* post message to HIDEngine */
MessagePut(0,msg);
}
/*
Removes all details of virtual cable
*/
void removeVirtualCable(void)
{
/* delete all knowledge of virtual cable */
dev_state.virtual_cable = FALSE;
memset(&dev_state.host_addr,0,sizeof(BD_ADDR_T));
/* delete the PS info by write length zero to it */
(void)PsStore(0,&dev_state.host_addr,sizeof(BD_ADDR_T));
}
/*
Sends a battery level report to the Host.
*/
void sendBatteryReport(uint16_t battery_level)
{
/*
TODO:
There is no standard method for HIDs to indicate their battery
level. All current wireless HID's use vendor specific reports
sent from their device which the vendor's Windows software
intercepts and processes.
Below is example code of how a vendor specific report could be
sent. The report must have a corresponding HID descriptor in
the device's SDP service record.
Note that is method of sending reports is slow and may add latency
to other reports in the pipeline. Sending a report will also
move the device back to the first powermode as if a key had been pressed,
so it is recommended that these are only sent during active power mode.
*/
#if 0
MAKE_MSG(HID_SEND_INPUT_REPORT_REQ);
/* create the report */
msg->data = (uint8_t *)malloc(sizeof(uint8_t)*3);
/* multiply battery level by two as there is divide by 2
potential divider on ADC input */
battery_level *=2;
msg->data[0] = 0x3; /* report ID 3 */
msg->data[1] = (battery_level & 0xff);
msg->data[2] = (battery_level >> 8);
msg->length = 3;
/* post message to HIDEngine */
MessagePut(0,msg);
#else
/* keep compiler happy */
battery_level = battery_level;
#endif
}
/*
Simple function that flashes the Num,Caps and Scroll Lock LEDs
when the keyboard is discoverable.
*/
Delay DiscoverableLEDFlasher(TimerHandle h)
{
h=h;
/* are they currently on? */
if (PioGet() & (NUM_LOCK | CAPS_LOCK | SCROLL_LOCK))
{
/* yes - turn them off */
PioSet(NUM_LOCK | CAPS_LOCK | SCROLL_LOCK, 0);
/* configure timer to turn LEDs on */
return D_mSEC(300);
}
else
{
/* no - turn them on */
PioSet(NUM_LOCK | CAPS_LOCK | SCROLL_LOCK, NUM_LOCK | CAPS_LOCK | SCROLL_LOCK);
/* configure timer to turn LEDs off */
return D_mSEC(100);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -