HID.c 6.39 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
/*
             LUFA Library
     Copyright (C) Dean Camera, 2009.
              
  dean [at] fourwalledcubicle [dot] com
      www.fourwalledcubicle.com
*/

/*
  Copyright 2009  Dean Camera (dean [at] fourwalledcubicle [dot] com)

  Permission to use, copy, modify, and distribute this software
  and its documentation for any purpose and without fee is hereby
  granted, provided that the above copyright notice appear in all
  copies and that both that the copyright notice and this
  permission notice and warranty disclaimer appear in supporting
  documentation, and that the name of the author not be used in
  advertising or publicity pertaining to distribution of the
  software without specific, written prior permission.

  The author disclaim all warranties with regard to this
  software, including all implied warranties of merchantability
  and fitness.  In no event shall the author be liable for any
  special, indirect or consequential damages or any damages
  whatsoever resulting from loss of use, data or profits, whether
  in an action of contract, negligence or other tortious action,
  arising out of or in connection with the use or performance of
  this software.
*/

31
32
33
#include "../../HighLevel/USBMode.h"
#if defined(USB_CAN_BE_DEVICE)

34
35
#include "HID.h"

36
void HID_Device_ProcessControlRequest(USB_ClassInfo_HID_Device_t* const HIDInterfaceInfo)
37
38
39
40
{
	if (!(Endpoint_IsSETUPReceived()))
	  return;
	  
41
42
	if (USB_ControlRequest.wIndex != HIDInterfaceInfo->Config.InterfaceNumber)
	  return;
43
44
45
46
47
48
49
50

	switch (USB_ControlRequest.bRequest)
	{
		case REQ_GetReport:
			if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
			{
				Endpoint_ClearSETUP();	

51
52
				uint16_t ReportINSize = 0;
				uint8_t  ReportID     = (USB_ControlRequest.wValue & 0xFF);
53
				uint8_t  ReportType   = (USB_ControlRequest.wValue >> 8) - 1;
54

55
				memset(HIDInterfaceInfo->Config.PrevReportINBuffer, 0, HIDInterfaceInfo->Config.PrevReportINBufferSize);
56
				
57
				CALLBACK_HID_Device_CreateHIDReport(HIDInterfaceInfo, &ReportID, ReportType,
58
				                                    HIDInterfaceInfo->Config.PrevReportINBuffer, &ReportINSize);
59

60
				Endpoint_SelectEndpoint(ENDPOINT_CONTROLEP);
61
				Endpoint_Write_Control_Stream_LE(HIDInterfaceInfo->Config.PrevReportINBuffer, ReportINSize);
62
63
64
65
66
67
68
69
70
71
72
				Endpoint_ClearOUT();
			}
		
			break;
		case REQ_SetReport:
			if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
			{
				Endpoint_ClearSETUP();
				
				uint16_t ReportOUTSize = USB_ControlRequest.wLength;
				uint8_t  ReportOUTData[ReportOUTSize];
73
				uint8_t  ReportID = (USB_ControlRequest.wValue & 0xFF);
74
75
76
77

				Endpoint_Read_Control_Stream_LE(ReportOUTData, ReportOUTSize);
				Endpoint_ClearIN();
				
78
				CALLBACK_HID_Device_ProcessHIDReport(HIDInterfaceInfo, ReportID, ReportOUTData, ReportOUTSize);
79
80
81
82
83
84
85
86
			}
			
			break;
		case REQ_GetProtocol:
			if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
			{
				Endpoint_ClearSETUP();

87
				Endpoint_Write_Byte(HIDInterfaceInfo->State.UsingReportProtocol);
88
89
				Endpoint_ClearIN();

90
				Endpoint_ClearStatusStage();
91
92
93
94
95
96
97
98
			}
			
			break;
		case REQ_SetProtocol:
			if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
			{
				Endpoint_ClearSETUP();

99
				HIDInterfaceInfo->State.UsingReportProtocol = ((USB_ControlRequest.wValue & 0xFF) != 0x00);
100
				
101
				Endpoint_ClearStatusStage();
102
103
104
105
106
107
			}
			
			break;
		case REQ_SetIdle:
			if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
			{
108
				Endpoint_ClearSETUP();
109
					
110
				HIDInterfaceInfo->State.IdleCount = ((USB_ControlRequest.wValue & 0xFF00) >> 6);
111
					
112
				Endpoint_ClearStatusStage();
113
114
115
116
117
118
119
120
			}
			
			break;
		case REQ_GetIdle:
			if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
			{		
				Endpoint_ClearSETUP();
				
121
				Endpoint_Write_Byte(HIDInterfaceInfo->State.IdleCount >> 2);
122
123
				Endpoint_ClearIN();

124
				Endpoint_ClearStatusStage();
125
126
127
128
129
130
			}

			break;
	}
}

131
bool HID_Device_ConfigureEndpoints(USB_ClassInfo_HID_Device_t* const HIDInterfaceInfo)
132
{
133
	memset(&HIDInterfaceInfo->State, 0x00, sizeof(HIDInterfaceInfo->State));
134
	HIDInterfaceInfo->State.UsingReportProtocol = true;
135
	HIDInterfaceInfo->State.IdleCount = 500;
136

137
	if (!(Endpoint_ConfigureEndpoint(HIDInterfaceInfo->Config.ReportINEndpointNumber, EP_TYPE_INTERRUPT,
138
139
									 ENDPOINT_DIR_IN, HIDInterfaceInfo->Config.ReportINEndpointSize,
									 HIDInterfaceInfo->Config.ReportINEndpointDoubleBank ? ENDPOINT_BANK_DOUBLE : ENDPOINT_BANK_SINGLE)))
140
141
142
143
144
145
146
	{
		return false;
	}
	
	return true;
}
		
147
void HID_Device_USBTask(USB_ClassInfo_HID_Device_t* const HIDInterfaceInfo)
148
{
149
	if (USB_DeviceState != DEVICE_STATE_Configured)
150
151
	  return;

152
	Endpoint_SelectEndpoint(HIDInterfaceInfo->Config.ReportINEndpointNumber);
153
	
154
	if (Endpoint_IsReadWriteAllowed())
155
	{
156
		uint8_t  ReportINData[HIDInterfaceInfo->Config.PrevReportINBufferSize];
157
158
		uint8_t  ReportID     = 0;
		uint16_t ReportINSize = 0;
159
160
161

		memset(ReportINData, 0, sizeof(ReportINData));

162
163
		bool ForceSend         = CALLBACK_HID_Device_CreateHIDReport(HIDInterfaceInfo, &ReportID, REPORT_ITEM_TYPE_In,
		                                                             ReportINData, &ReportINSize);
164
		bool StatesChanged     = false;
165
166
		bool IdlePeriodElapsed = (HIDInterfaceInfo->State.IdleCount && !(HIDInterfaceInfo->State.IdleMSRemaining));
		
167
168
169
170
171
		if (HIDInterfaceInfo->Config.PrevReportINBuffer != NULL)
		{
			StatesChanged = (memcmp(ReportINData, HIDInterfaceInfo->Config.PrevReportINBuffer, ReportINSize) != 0);
			memcpy(HIDInterfaceInfo->Config.PrevReportINBuffer, ReportINData, ReportINSize);
		}
172

173
		if (ReportINSize && (ForceSend || StatesChanged || IdlePeriodElapsed))
174
		{
175
176
			HIDInterfaceInfo->State.IdleMSRemaining = HIDInterfaceInfo->State.IdleCount;

177
178
			Endpoint_SelectEndpoint(HIDInterfaceInfo->Config.ReportINEndpointNumber);

179
			if (ReportID)
180
			  Endpoint_Write_Byte(ReportID);
181
182

			Endpoint_Write_Stream_LE(ReportINData, ReportINSize, NO_STREAM_CALLBACK);
183
184
			
			Endpoint_ClearIN();
185
186
187
		}
	}
}
188

189
190
191
192
193
194
void HID_Device_MillisecondElapsed(USB_ClassInfo_HID_Device_t* HIDInterfaceInfo)
{
	if (HIDInterfaceInfo->State.IdleMSRemaining)
	  HIDInterfaceInfo->State.IdleMSRemaining--;
}

195
#endif