-
Notifications
You must be signed in to change notification settings - Fork 1
/
libusb1_lvrhid8.c
188 lines (163 loc) · 5.31 KB
/
libusb1_lvrhid8.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
#include <errno.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <libusb-1.0/libusb.h>
#define VERSION "0.1.0"
#define VENDOR_ID 0x0925
#define PRODUCT_ID 0x7001
// HID Class-Specific Requests values. See section 7.2 of the HID specifications
#define HID_GET_REPORT 0x01
#define HID_GET_IDLE 0x02
#define HID_GET_PROTOCOL 0x03
#define HID_SET_REPORT 0x09
#define HID_SET_IDLE 0x0A
#define HID_SET_PROTOCOL 0x0B
#define HID_REPORT_TYPE_INPUT 0x01
#define HID_REPORT_TYPE_OUTPUT 0x02
#define HID_REPORT_TYPE_FEATURE 0x03
#define CTRL_IN LIBUSB_ENDPOINT_IN|LIBUSB_REQUEST_TYPE_CLASS|LIBUSB_RECIPIENT_INTERFACE
#define CTRL_OUT LIBUSB_ENDPOINT_OUT|LIBUSB_REQUEST_TYPE_CLASS|LIBUSB_RECIPIENT_INTERFACE
const static int PACKET_CTRL_LEN=3;
const static int PACKET_INT_LEN=3;
const static int ENDPOINT_INT_IN=0x81; /* endpoint 0x81 address for IN */
const static int ENDPOINT_INT_OUT=0x01; /* endpoint 1 address for OUT */
const static int TIMEOUT=5000; /* timeout in ms */
void bad(const char *why) {
fprintf(stderr,"Fatal error> %s\n",why);
exit(17);
}
static struct libusb_device_handle *devh = NULL;
static int find_lvr_hidusb(void)
{
devh = libusb_open_device_with_vid_pid(NULL, VENDOR_ID, PRODUCT_ID);
return devh ? 0 : -EIO;
}
static int test_control_transfer_feature(void)
{
int r,i;
char answer[PACKET_CTRL_LEN];
char question[PACKET_CTRL_LEN];
question[0]=3; //Feature Out Report ID: 3
for (i=1;i<=PACKET_CTRL_LEN; i++) question[i]=0x20+i;
answer[0]=0; //Feature In Report ID, is 4, but just initiate it to be 0, it should return 4
for (i=1;i<=PACKET_CTRL_LEN; i++) answer[i]=0;
r = libusb_control_transfer(devh,CTRL_OUT,HID_SET_REPORT,(HID_REPORT_TYPE_FEATURE<<8)|0x03, 0,question, PACKET_CTRL_LEN,TIMEOUT);
if (r < 0) {
fprintf(stderr, "Control Out error %d\n", r);
return r;
}
r = libusb_control_transfer(devh,CTRL_IN,HID_GET_REPORT,(HID_REPORT_TYPE_FEATURE<<8)|0x04, 0, answer,PACKET_CTRL_LEN, TIMEOUT);
if (r < 0) {
fprintf(stderr, "Control IN error %d\n", r);
return r;
}
for(i = 0;i <= PACKET_CTRL_LEN; i++) {
if(i%8 == 0)
printf("\n");
printf("%02x, %02x; ",question[i],answer[i]);
}
printf("\n");
return 0;
}
static int test_control_transfer_in_out(void)
{
int r,i;
char answer[PACKET_INT_LEN];
char question[PACKET_INT_LEN];
question[0]=2; //Output Report ID is 2
for (i=1;i<=PACKET_INT_LEN; i++) question[i]=0x30+i;
answer[0]=0; //Input Report ID, is 1, just set it to 0, it should return 1.
for (i=1;i<=PACKET_INT_LEN; i++) answer[i]=0;
r = libusb_control_transfer(devh,CTRL_OUT,HID_SET_REPORT,(HID_REPORT_TYPE_OUTPUT<<8)|0x02, 0,question, PACKET_INT_LEN,TIMEOUT);
if (r < 0) {
fprintf(stderr, "Control Out error %d\n", r);
return r;
}
r = libusb_control_transfer(devh,CTRL_IN,HID_GET_REPORT,(HID_REPORT_TYPE_INPUT<<8)|0x01, 0, answer,PACKET_INT_LEN, TIMEOUT);
if (r < 0) {
fprintf(stderr, "Control IN error %d\n", r);
return r;
}
for(i = 0;i <= PACKET_INT_LEN; i++) {
if(i%8 == 0)
printf("\n");
printf("%02x, %02x; ",question[i],answer[i]);
}
printf("\n");
return 0;
}
static int test_interrupt_transfer(void)
{
int r,i;
int transferred;
char answer[PACKET_INT_LEN];
char question[PACKET_INT_LEN];
question[0]=2; //Output report ID
for (i=1;i<=PACKET_INT_LEN; i++) question[i]=0x40+i;
answer[0]=0; //Input Report ID, is 1, just set it to 0, it should return 1
for (i=1;i<=PACKET_INT_LEN; i++) answer[i]=0;
r = libusb_interrupt_transfer(devh, ENDPOINT_INT_OUT, question, PACKET_INT_LEN, &transferred,TIMEOUT);
if (r < 0) {
fprintf(stderr, "Interrupt write error %d\n", r);
return r;
}
r = libusb_interrupt_transfer(devh, ENDPOINT_INT_IN, answer,PACKET_INT_LEN, &transferred, TIMEOUT);
if (r < 0) {
fprintf(stderr, "Interrupt read error %d\n", r);
return r;
}
if (transferred < PACKET_INT_LEN) {
fprintf(stderr, "Interrupt transfer short read (%d)\n", r);
return -1;
}
for(i = 0;i <= PACKET_INT_LEN; i++) {
if(i%8 == 0)
printf("\n");
printf("%02x, %02x; ",question[i],answer[i]);
}
printf("\n");
return 0;
}
int main(void)
{
int r = 1;
r = libusb_init(NULL);
if (r < 0) {
fprintf(stderr, "Failed to initialise libusb\n");
exit(1);
}
r = find_lvr_hidusb();
if (r < 0) {
fprintf(stderr, "Could not find/open LVR Generic HID device\n");
goto out;
}
printf("Successfully find the LVR Generic HID device\n");
#ifdef LINUX
libusb_detach_kernel_driver(devh, 0);
#endif
r = libusb_set_configuration(devh, 1);
if (r < 0) {
fprintf(stderr, "libusb_set_configuration error %d\n", r);
goto out;
}
printf("Successfully set usb configuration 1\n");
r = libusb_claim_interface(devh, 0);
if (r < 0) {
fprintf(stderr, "libusb_claim_interface error %d\n", r);
goto out;
}
printf("Successfully claimed interface\n");
printf("Testing control transfer using loop back test of feature report");
test_control_transfer_feature();
printf("Testing control transfer using loop back test of input/output report");
test_control_transfer_in_out();
printf("Testing interrupt transfer using loop back test of input/output report");
test_interrupt_transfer();
libusb_release_interface(devh, 0);
out:
// libusb_reset_device(devh);
libusb_close(devh);
libusb_exit(NULL);
return r >= 0 ? r : -r;
}