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

📄 events.c

📁 蓝牙无线鼠标软件代码。采用CSR公司的BLUELAB27模式。有很好的参考价值。
💻 C
字号:
/****************************************************************************

  Copyright (C) Cambridge Silicon Radio 2002

FILE
        events.c - file for handling events generated by VM and HIDEngine

MODIFICATION HISTORY


*****************************************************************************/
#include <stdlib.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 <batt.h>
#include <hid.h>
#include "mouse.h"

/*
	Globals
*/
extern DEVICE_STATE_T	dev_state;

/*
	Prototypes for static functions
*/
static void handleInitCfm(const HID_INIT_CFM_T *prim);
static void handleConnectCfm(const HID_CONNECT_CFM_T *prim);
static void handleDisconnectInd(const HID_DISCONNECT_IND_T *prim);
static void handleDisconnectCfm(void);
static void handlePinRequest(void);
static void handlePowerMode(const HID_POWER_MODE_IND_T *prim);
static void handleButtonPress(void);

/*
	This is called by the VM to tell us about our battery level
*/
void handleBatteryReading(uint16 millivolts)
{
	/* only monitor battery if in report mode and active */
	if ((dev_state.protocol == HIDPROTOCOL_REPORT) && (dev_state.power_mode==0))
	{
		/* send report */
		sendBatteryReport(millivolts);
	}
}


/*
	This is called by the VM when one of the mask PIO lines changes
*/
static void applicationPioEvent(uint16 pins)
{
	/* is button down? */
    if(pins & CONNECT_BUTTON)
		handleButtonPress();
}

/*
	Define scheduler behaviour to call function above on button press.
*/
static const uint16 applicationPins = CONNECT_BUTTON;
const SchedPioEntry applicationPioEntry = { &applicationPins, applicationPioEvent };


/*
	Responds to the user pressing the connect button.

	We always want to get into discoverable mode and if
	possible tell the current host that we no longer want
	to be associated with it.
*/
static void handleButtonPress(void)
{
	/* clear flag */
	dev_state.button_press_pending = FALSE;

	/* process button press depending on our current state */
	switch (dev_state.state)
	{
		case unconnected:
			/* unconnected so start discoverable */
			connect(host_to_discover_and_connect);
			break;

		case connected:
			/* still unable to process request */
			dev_state.button_press_pending = TRUE;
			/* button pressed during connect - unplug virtual cable */
			disconnect(TRUE);
			break;

		case connecting:
			/* we can't handle this now, so mark pending button press and try
			   to cancel connection */
			dev_state.button_press_pending = TRUE;
			cancelConnect();
			break;

		case disconnecting:
			/* wait for disconnect to finish before processing */
			dev_state.button_press_pending = TRUE;
			break;

		case discoverable:
			/* cancel current discoverable mode and restart.
			   this allows user to extend the discoverable period. */
			dev_state.button_press_pending = TRUE;
			cancelConnect();
			break;

		case init:
			/* ignore when initialising */	
	}
}

/*
	This is called when the HIDEngine has posted us a message.
*/
DECLARE_TASK(2)
{
    MessageType type;
    void *data = MessageGet(2,&type);
    
	if (data)
	{
		/* handle the message depending on its type */
		switch(type)
		{
			/*
				HID Engine events - defined below
			*/
			case HID_INIT_CFM:
				handleInitCfm((HID_INIT_CFM_T*)data);
				break;
			case HID_CONNECT_CFM:
				handleConnectCfm((HID_CONNECT_CFM_T*)data);
				break;
			case HID_DISCONNECT_IND:
				handleDisconnectInd((HID_DISCONNECT_IND_T*)data);
				break;			
			case HID_DISCONNECT_CFM:
				handleDisconnectCfm();
				break;
			case HID_PIN_CODE_IND:
				handlePinRequest();
				break;
			case HID_POWER_MODE_IND:
				handlePowerMode((HID_POWER_MODE_IND_T*)data);
				break;

			/*
				Protocol events - see protocol.c
			*/
			case HID_CONTROL_IND:
				handleControl((HID_CONTROL_IND_T*)data);
				break;
			case HID_SET_PROTOCOL_IND:
				handleSetProtocol((HID_SET_PROTOCOL_IND_T*)data);
				break;
			case HID_GET_PROTOCOL_IND:
				handleGetProtocol((HID_GET_PROTOCOL_IND_T*)data);
				break;
			case HID_SET_IDLE_IND:
				handleSetIdle((HID_SET_IDLE_IND_T*)data);
				break;
			case HID_GET_IDLE_IND:
				handleGetIdle((HID_GET_IDLE_IND_T*)data);
				break;
			case HID_GET_REPORT_IND:
				handleGetReport((HID_GET_REPORT_IND_T*)data);
				break;
			case HID_SET_REPORT_IND:
				handleSetReport((HID_SET_REPORT_IND_T*)data);
				break;
			default:
		}

		/* free the message */
		MessageDestroy(data);
	}
}

/*
	The HIDEngine has responded to our initialisation request.
*/
static void handleInitCfm(const HID_INIT_CFM_T *prim)
{
	if (prim->result == RES_SUCCESS)
	{
		/* we are now unconnected */
		dev_state.state = unconnected;

		/* if we have a virtual cable, we will try and reconnect now */
		if (dev_state.virtual_cable)
		{
			/* attempt to reconnect */
			connect(reconnect_to_host);
		}
		else
		{
			/* power on with no virtual cable - allow ourselves to be discovered */
			connect(host_to_discover_and_connect);
		}
	}
}

/*
	A response to our CONNECT_REQ has been generated.
*/
static void handleConnectCfm(const HID_CONNECT_CFM_T *prim)
{
	/* turn off status LED */
	PioSet(STATUS_LED1 | STATUS_LED2, STATUS_LED1 | STATUS_LED2);

	/* are we connected? */
	if (prim->result == RES_SUCCESS)
	{
		/* if this first connection after discovery we have new virtual cable */
		if (dev_state.state == discoverable)
		{
			/* store virtual cable info */
			dev_state.host_addr = prim->host_addr;
			(void)PsStore(0,&dev_state.host_addr,sizeof(BD_ADDR_T));
			dev_state.virtual_cable = TRUE;
		}

		/* now connected */
		dev_state.state = connected;

		/*
			start the battery monitor
			(batt lib takes four samples before return value, so pass 1/4 time)
		*/
		BattInit(VM_ADC_TEST_A, D_SEC((BATTERY_SAMPLE_RATE+3)/4));

		/* if the connect button was pressed during a connect scenario, handle it now */
		if (dev_state.button_press_pending)
		{
			handleButtonPress();
		}
	}
	else
	{
		/* failed - still unconnected */
		dev_state.state = unconnected;

		/* if the connect button was pressed during a connect scenario, handle it now */
		if (dev_state.button_press_pending)
		{
			handleButtonPress();
		}
		else if (dev_state.virtual_cable)
		/* if we have a virtual cabled host then attempt to reconnect
		   when the mouse is moved */
		{
			connect(reconnect_to_host_on_data);
		}
	}
}

/*
	The HID connection has be terminated
*/
static void handleDisconnectInd(const HID_DISCONNECT_IND_T *prim)
{
	prim = prim;

	/* we are now unconnected - reset state */
	dev_state.state = unconnected;
	dev_state.protocol = HIDPROTOCOL_REPORT;

	/* stop the battery monitor */
	BattInit(VM_ADC_TEST_A, D_NEVER);

	/* look at the reason for the connection being lost and
	   respond accordingly */
	switch (prim->reason)
	{
		/*
			LinkLoss:
			Assume that this will only occur when we are out
			of range or the Host has unexpectly reset.
			We will try to reconnect immediately to regain
			the connection.
		*/
		case LINKLOSS:
			connect(reconnect_to_host);
			break;

		/*
			Unplug:
			The Host has unplugged and disconnected us.
			We delete our virtual cable info and wait
			for the user to press the connect button.
		*/
		case VIRTUAL_CABLE_UNPLUG:
			removeVirtualCable();
			break;

		/*
			HostDisconnect:
			The host has disconnected us, probably because it
			has shutdown.
			We will attempt a reconnect when the mouse is moved.

			PowerModeDisconnect:
			We have not sent any data for a while so powermanagement
			has disconnected us.
			Reconnect when we have data
		*/
		case HOST_DISCONNECT:
		case POWER_MODE_DISCONNECT:
			/* reconnect when we have data */
			connect(reconnect_to_host_on_data);
			break;
		default:
	}
}

/*
	The HIDEngine is reporting that our DISCONNECT_REQ was successful
*/
static void handleDisconnectCfm(void)
{
	/* we are now unconnected - reset state */
	dev_state.state = unconnected;
	dev_state.protocol = HIDPROTOCOL_REPORT;

	/* stop the battery monitor */
	BattInit(VM_ADC_TEST_A, D_NEVER);

	/* if the connect button was pressed during a disconnect, handle it now */
	if (dev_state.button_press_pending)
	{
		handleButtonPress();
	}
	else if (dev_state.virtual_cable)
	/* our suspend behaviour is to disconnect and reconnect on data,
	   so if we disconnect but still have a virtual cable we should
	   reconnect when the mouse is moved. */
	{
		connect(reconnect_to_host_on_data);
	}
}

/*
	The Host has requested that we authenticate and requires a
	PIN code.
	We currently reply with the HID default PIN, but for security
	it is advised that the device has at least a fixed 4 digit PIN.
*/
static void handlePinRequest(void)
{
	MAKE_MSG(HID_PIN_CODE_RSP);	
	
	/* reply with a PIN code of 0000*/
	msg->pin[0] = '0';
	msg->pin[1] = '0';
	msg->pin[2] = '0';
	msg->pin[3] = '0';
	msg->pin_length = 4;

	MessagePut(0,msg);
}

/*
	The HID library has changed to a different powermode in
	the PowerTable we passed during initialisation.
	The value 'mode' tells us which mode, 0 being the first.
*/
static void handlePowerMode(const HID_POWER_MODE_IND_T *prim)
{
	dev_state.power_mode = prim->mode;
}

⌨️ 快捷键说明

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