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

📄 protocol.c

📁 hid_keyboard
💻 C
字号:
/****************************************************************************

  Copyright (C) Cambridge Silicon Radio 2002

FILE
        protocol.c - processing of HID protocol events

MODIFICATION HISTORY


*****************************************************************************/
#include <stdlib.h>
#include <message.h>
#include <hid.h>
#include <pio.h>
#include "keyboard.h"

/*
	Globals
*/
extern DEVICE_STATE_T	dev_state;

/*
	Process a HIDCONTROL command
*/
void handleControl(const HID_CONTROL_IND_T *prim)
{
	switch (prim->op)
	{
		/*
			Entering suspend mode.
			To save power, we will disconnect and reconnect when a
			key is pressed.  The Host should support this because
			we have RemoteWake and ReconnectInitiate set in our service record.
		*/
		case HID_COP_SUSPEND:
			disconnect(FALSE);
			break;

		/*
			This shouldn't happen as we are disconnected during suspend!			
		*/
		case HID_COP_EXITSUSPEND:
			break;
		default:
	}
}


/*
	The Host has sent us a report on either the control or interrupt channel.
	We first need to check if it is valid according to our HID Report Descriptor,
	and then extract the data.
*/
void handleSetReport(const HID_SET_REPORT_IND_T *prim)
{
	MAKE_MSG(HID_SET_REPORT_RSP);

	/* pass back the identifier */
	msg->identifier	= prim->identifier;

	/* check it's the correct report type and correct length
	   (Note that the Host can append random data to the end of a packet) */
	if ((prim->report_type == HIDREPORT_OUTPUT) && (prim->report_length >= 2))
	{
		/* check for our report ID */
		if (prim->data[0] == 1)
		{
			uint16 leds = 0;

			/* store the passed state for later */
			dev_state.led_state = prim->data[1] & 7;			

			if (prim->data[1] & 1)
				leds |= NUM_LOCK;
			if (prim->data[1] & 2)
				leds |= CAPS_LOCK;
			if (prim->data[1] & 4)
				leds |= SCROLL_LOCK;

			PioSet(NUM_LOCK | CAPS_LOCK | SCROLL_LOCK, leds);

			msg->result = RES_SUCCESS;
		}
		else
			/* invalid report ID */
			msg->result = RES_INVALIDID;
	}
	else
		/* unexpected */
		msg->result = RES_INVALIDPARAM;

	/* free the report */
	free(prim->data);

	/* send reply */
	MessagePut(0,msg);
}	

/*
	The Host has requested that we change our protocol.
	Store the new protocol and respond with success.
*/
void handleSetProtocol(const HID_SET_PROTOCOL_IND_T *prim)
{
	MAKE_MSG(HID_SET_PROTOCOL_RSP);	
	
	/* store the protocol */
	dev_state.protocol = prim->protocol;
	
	msg->result = RES_SUCCESS;

	MessagePut(0,msg);	 
}

/*
	The Host has requested our current protocol.
	Respond with success and send our protocol.
*/
void handleGetProtocol(const HID_GET_PROTOCOL_IND_T *prim)
{
	MAKE_MSG(HID_GET_PROTOCOL_RSP);
	prim = prim;
	
	msg->result = RES_SUCCESS;
	msg->protocol = dev_state.protocol;

	MessagePut(0,msg);
}

/*
	The Host has requested that we change our idle rate.
*/
void handleSetIdle(const HID_SET_IDLE_IND_T *prim)
{
	MAKE_MSG(HID_SET_IDLE_RSP);	

	/* We don't want to enter an idle mode which could
	   cause us to run at a very high rate.  We therefore
	   only allow a zero value or one greater than 5 (>20ms) */
	if ((prim->idle == 0) || (prim->idle >= 5))
	{
		/* Store the rate and return success.
		   Note that the HID library handles the actual
		   sample rate adjustments for idle mode */
		dev_state.idle = prim->idle;

		msg->result = RES_SUCCESS;
		
		/* if we are in IDLE mode (non-zero value), we need to
		   signal this to the external procesor.  The processor
		   should see this and send the current keystate on
		   every poll from the UART interface. */
		if (prim->idle)
			PioSet(IDLE_MODE,IDLE_MODE);
		else
			PioSet(IDLE_MODE,0);
	}
	else
		/* reject the value */
		msg->result = RES_INVALIDPARAM;

	MessagePut(0,msg);
}

/*
	The Host has requested our current idle rate.
*/
void handleGetIdle(const HID_GET_IDLE_IND_T *prim)
{
	MAKE_MSG(HID_GET_IDLE_RSP);	

	prim=prim;

	/* reply with our current rate */
	msg->result = RES_SUCCESS;
	msg->idle = dev_state.idle;
	
	MessagePut(0,msg);	 
}

/*
	The Host has requested a report.
	Keyboard reports are sent without our knowledge
	so we do not know the current state.
	This is usually called on startup, so returning
	no keys down, we should be ok.
*/
void handleGetReport(const HID_GET_REPORT_IND_T *prim)
{
	MAKE_MSG(HID_GET_REPORT_RSP);
	
	/* Is it asking for our input report? */
	if (prim->report_type == HIDREPORT_INPUT)
	{
		/*
			We only support one report which has an ID of 1.
			This will also be the case in boot mode.

			Note that we deliberately don't respond to requests
			for the PIN entry report because it is only active for
			a very short time.
		*/
		if (prim->report_id == 1)
		{
			/*
				we don't know the current state, so we send
				an "empty report"
			*/
			msg->report_type = HIDREPORT_INPUT;
			msg->data = (uint8_t *)calloc(9,sizeof(uint8_t));

			if (!msg->data)
				/* Allocation failed probably because something else
				   is happening.  We return BUSY which tells the host
				   to try again later */
				msg->result = RES_BUSY;
			else
			{
				/* set the report ID which leaves all other entries as zero */
				msg->data[0] = 1;

				/* clip length to only send what fits in Host's buffer */
				if (prim->buffer_size < 9)
					msg->report_length = prim->buffer_size;
				else
					msg->report_length = 9;
				
				/* return succesful */
				msg->result = RES_SUCCESS;	
			}
		}
		else
			/* this is not a valid ID */
			msg->result = RES_INVALIDID;	
	}
	/* Is it an output report? */
	else if (prim->report_type == HIDREPORT_OUTPUT)
	{
		/* LED report */
		if (prim->report_id == 1)
		{
			msg->report_type = HIDREPORT_OUTPUT;
			msg->data = (uint8_t *)malloc(2*sizeof(uint8_t));

			if (!msg->data)
				/* Allocation failed probably because something else
				   is happening.  We return BUSY which tells the host
				   to try again later */
				msg->result = RES_BUSY;
			else
			{
				msg->data[0] = 1;
				msg->data[1] = dev_state.led_state;

				/* clip length to only send what fits in Host's buffer */
				if (prim->buffer_size < 2)
					msg->report_length = prim->buffer_size;
				else
					msg->report_length = 2;
				
				/* return succesful */
				msg->result = RES_SUCCESS;				
			}
		}
		else
			/* this is not a valid ID */
			msg->result = RES_INVALIDID;
	}
	else
	{
		/* return invalid param for any other report type */
		msg->result = RES_INVALIDPARAM;
	}

	MessagePut(0,msg);
}



⌨️ 快捷键说明

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