-
Notifications
You must be signed in to change notification settings - Fork 7
/
Copy pathHID.c
200 lines (196 loc) · 10.5 KB
/
HID.c
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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
/* HID class support functions */
#include "project_config.h"
extern char bigbuf[]; //256 bytes
extern DEV_RECORD devtable[];
HID_DEVICE hid_device = {{ 0 }};
EP_RECORD hid_ep[ 2 ] = {{ 0 }}; //HID class endpoints, 1 control, 1 interrupt-IN
//the third endpoint is not implemented
/* HID Mouse probe. Called from USB state machine. */
/* assumes configuration length is less than 256 bytes */
/* looks for Class:03, Subclass: 01, Protocol: 02 in interface descriptor */
/* sets mouse in boot protocol */
/* assumes single configuration and interface configuration 0 */
BOOL HIDMProbe( BYTE addr, DWORD flags )
{
BYTE tmpbyte;
BYTE rcode;
BYTE confvalue;
WORD total_length;
USB_DESCR* data_ptr = ( USB_DESCR * )&bigbuf;
char* byte_ptr = bigbuf;
rcode = XferGetConfDescr( addr, 0, CONF_DESCR_LEN, 0, bigbuf ); //get configuration descriptor
if( rcode ) { //error handling
return( FALSE );
}
if( data_ptr->descr.config.wTotalLength > 256 ) {
total_length = 256;
}
else {
total_length = data_ptr->descr.config.wTotalLength;
}
rcode = XferGetConfDescr( addr, 0, total_length, 0, bigbuf ); //get the whole configuration
if( rcode ) { //error handling
return( FALSE );
}
confvalue = data_ptr->descr.config.bConfigurationValue;
while( byte_ptr < bigbuf + total_length ) {
if( data_ptr->descr.config.bDescriptorType != USB_DESCRIPTOR_INTERFACE ) {
byte_ptr = byte_ptr + data_ptr->descr.config.bLength;
data_ptr = ( USB_DESCR* )byte_ptr;
}// if( data_ptr->descr.config.bDescriptorType != USB_DESCRIPTOR_INTERFACE
else { //interface descriptor
if( data_ptr->descr.interface.bInterfaceClass == HID_INTF &&
data_ptr->descr.interface.bInterfaceSubClass == BOOT_INTF_SUBCLASS &&
data_ptr->descr.interface.bInterfaceProtocol == HID_PROTOCOL_MOUSE ) {
devtable[ addr ].devclass = HID_M; //device class
tmpbyte = devtable[ addr ].epinfo->MaxPktSize;
HID_init(); //initialize data structures
devtable[ addr ].epinfo = hid_ep; //switch endpoint information structure
devtable[ addr ].epinfo[ 0 ].MaxPktSize = tmpbyte;
hid_device.interface = data_ptr->descr.interface.bInterfaceNumber;
hid_device.addr = addr;
byte_ptr = byte_ptr + data_ptr->descr.config.bLength;
data_ptr = ( USB_DESCR* )byte_ptr;
while( byte_ptr < bigbuf + total_length ) {
if( data_ptr->descr.config.bDescriptorType != USB_DESCRIPTOR_ENDPOINT ) { //skip to endpoint descriptor
byte_ptr = byte_ptr + data_ptr->descr.config.bLength;
data_ptr = ( USB_DESCR* )byte_ptr;
}
else {
/* fill endpoint information structure */
devtable[ addr ].epinfo[ 1 ].epAddr = data_ptr->descr.endpoint.bEndpointAddress;
devtable[ addr ].epinfo[ 1 ].Attr = data_ptr->descr.endpoint.bmAttributes;
devtable[ addr ].epinfo[ 1 ].MaxPktSize = data_ptr->descr.endpoint.wMaxPacketSize;
devtable[ addr ].epinfo[ 1 ].Interval = data_ptr->descr.endpoint.bInterval;
// devtable[ addr ].epinfo[ 1 ].rcvToggle = bmRCVTOG0;
/* configure device */
rcode = XferSetConf( addr, 0, confvalue ); //set configuration
if( rcode ) { //error handling
return( FALSE );
}
rcode = XferSetProto( addr, 0, hid_device.interface, BOOT_PROTOCOL );
if( rcode ) { //error handling
return( FALSE );
}
else {
return( TRUE );
}
}
}//while( byte_ptr....
}//if (Class matches
else { //if class don't match; die on first interface. Not really correct
return( FALSE );
}
}//else if( data_ptr->
}// while( byte_ptr < &buf + total_length
return( FALSE );
}
/* HID Keyboard probe. Called from USB state machine. */
/* assumes configuration length is less than 256 bytes */
/* looks for Class:03, Subclass: 01, Protocol: 01 in interface descriptor */
/* sets keyboard in boot protocol */
/* assumes single configuration, single endpoint, and interface configuration 0 */
BOOL HIDKProbe( BYTE addr, DWORD flags )
{
BYTE tmpbyte;
BYTE rcode;
BYTE confvalue;
WORD total_length;
USB_DESCR* data_ptr = ( USB_DESCR * )&bigbuf;
char* byte_ptr = bigbuf;
rcode = XferGetConfDescr( addr, 0, CONF_DESCR_LEN, 0, bigbuf ); //get configuration descriptor
if( rcode ) { //error handling
return( FALSE );
}
if( data_ptr->descr.config.wTotalLength > 256 ) {
total_length = 256;
}
else {
total_length = data_ptr->descr.config.wTotalLength;
}
rcode = XferGetConfDescr( addr, 0, total_length, 0, bigbuf ); //get the whole configuration
if( rcode ) { //error handling
return( FALSE );
}
confvalue = data_ptr->descr.config.bConfigurationValue; //save configuration value to use later
while( byte_ptr < bigbuf + total_length ) { //parse configuration
if( data_ptr->descr.config.bDescriptorType != USB_DESCRIPTOR_INTERFACE ) { //skip to the next descriptor
byte_ptr = byte_ptr + data_ptr->descr.config.bLength;
data_ptr = ( USB_DESCR* )byte_ptr;
}// if( data_ptr->descr.config.bDescriptorType != USB_DESCRIPTOR_INTERFACE
else { //interface descriptor
if( data_ptr->descr.interface.bInterfaceClass == HID_INTF &&
data_ptr->descr.interface.bInterfaceSubClass == BOOT_INTF_SUBCLASS &&
data_ptr->descr.interface.bInterfaceProtocol == HID_PROTOCOL_KEYBOARD ) {
devtable[ addr ].devclass = HID_K; //fill device class
tmpbyte = devtable[ addr ].epinfo->MaxPktSize; //save max.packet size
HID_init(); //initialize data structures
devtable[ addr ].epinfo = hid_ep; //switch endpoint information structure
devtable[ addr ].epinfo[ 0 ].MaxPktSize = tmpbyte; //fill in max.packet size
hid_device.interface = data_ptr->descr.interface.bInterfaceNumber; //fill in interface number to be used in HID requests
hid_device.addr = addr; //fill in address
byte_ptr = byte_ptr + data_ptr->descr.config.bLength; //skip to the next descriptor
data_ptr = ( USB_DESCR* )byte_ptr;
while( byte_ptr < bigbuf + total_length ) {
if( data_ptr->descr.config.bDescriptorType != USB_DESCRIPTOR_ENDPOINT ) { //skip to endpoint descriptor
byte_ptr = byte_ptr + data_ptr->descr.config.bLength;
data_ptr = ( USB_DESCR* )byte_ptr;
}
else {
/* fill endpoint information structure */
devtable[ addr ].epinfo[ 1 ].epAddr = data_ptr->descr.endpoint.bEndpointAddress;
devtable[ addr ].epinfo[ 1 ].Attr = data_ptr->descr.endpoint.bmAttributes;
devtable[ addr ].epinfo[ 1 ].MaxPktSize = data_ptr->descr.endpoint.wMaxPacketSize;
devtable[ addr ].epinfo[ 1 ].Interval = data_ptr->descr.endpoint.bInterval;
/* configure device */
rcode = XferSetConf( addr, 0, confvalue ); //set configuration
if( rcode ) { //error handling
return( FALSE );
}
rcode = XferSetProto( addr, 0, hid_device.interface, BOOT_PROTOCOL );
if( rcode ) { //error handling
return( FALSE );
}
else {
return( TRUE );
}
}
}//while( byte_ptr....
}//if (Class matches
else { //if class don't match; stop processing after first interface. Not really correct
return( FALSE );
}
}//else if( data_ptr->
}// while( byte_ptr < &buf + total_length
return( FALSE );
}
/* HID data structures initialization */
void HID_init( void )
{
hid_ep[ 1 ].sndToggle = bmSNDTOG0;
hid_ep[ 1 ].rcvToggle = bmRCVTOG0;
}
/* poll boot mouse */
BYTE mousePoll( BOOT_MOUSE_REPORT* buf )
{
BYTE rcode;
MAXreg_wr( rPERADDR, hid_device.addr ); //set peripheral address
rcode = XferInTransfer( hid_device.addr, 1, 8, ( char* )buf, devtable[ hid_device.addr ].epinfo[ 1 ].MaxPktSize );
return( rcode );
}
/* poll boot keyboard */
BYTE kbdPoll( BOOT_KBD_REPORT* buf )
{
BYTE rcode;
MAXreg_wr( rPERADDR, hid_device.addr ); //set peripheral address
rcode = XferInTransfer( hid_device.addr, 1, 8, ( char* )buf, devtable[ hid_device.addr ].epinfo[ 1 ].MaxPktSize );
return( rcode );
}
BOOL HIDMEventHandler( BYTE address, BYTE event, void *data, DWORD size )
{
return( FALSE );
}
BOOL HIDKEventHandler( BYTE address, BYTE event, void *data, DWORD size )
{
return( FALSE );
}