-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathusbcommon.c
More file actions
131 lines (120 loc) · 4.34 KB
/
usbcommon.c
File metadata and controls
131 lines (120 loc) · 4.34 KB
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
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "usbcommon.h"
const uint16_t VENDOR_ID = 0x045e;
const uint16_t PRODUCT_ID = 0x02ea;
void print_libusb_version(void)
{
const struct libusb_version *version = libusb_get_version();
printf("libusb v%u.%u.%u.%u%s (%s)\n",
version->major, version->minor, version->micro, version->nano,
version->rc, version->describe);
}
// Convert an array of integers to a comma-separated string
// WARNING: Buffer overflow is possible if `str` is too small
char *join(int len, const uint8_t nums[len], char str[])
{
char num[8];
str[0] = '\0';
for (int i = 0; i < len; i++) {
snprintf(num, sizeof(num), "%u,", nums[i]);
strcat(str, num);
}
if (len > 0) {
str[strlen(str) - 1] = '\0'; // remove trailing comma
}
return str;
}
void print_port_path(libusb_device_handle *devh)
{
uint8_t port_numbers[8];
libusb_device *dev = libusb_get_device(devh);
const int ports = libusb_get_port_numbers(dev, port_numbers, sizeof(port_numbers));
char port_path[20];
join(ports, port_numbers, port_path);
printf("Port path: %s\n", port_path);
}
void printhex(int len, const uint8_t data[len])
{
for (int i = 0; i < len; i++) {
printf("%02X", data[i]);
}
}
// The `data` array must be at least 18 bytes in length
void data_to_gamepad(const uint8_t data[18], struct gamepad_t *gamepad)
{
gamepad->type = data[0];
gamepad->const_0 = data[1];
gamepad->id = data[2];
gamepad->length = data[3];
gamepad->a = data[4] & 0x10 ? 1 : 0;
gamepad->b = data[4] & 0x20 ? 1 : 0;
gamepad->x = data[4] & 0x40 ? 1 : 0;
gamepad->y = data[4] & 0x80 ? 1 : 0;
gamepad->sync = data[4] & 0x01 ? 1 : 0;
gamepad->menu = data[4] & 0x04 ? 1 : 0;
gamepad->view = data[4] & 0x08 ? 1 : 0;
gamepad->lbumper = data[5] & 0x10 ? 1 : 0;
gamepad->rbumper = data[5] & 0x20 ? 1 : 0;
gamepad->lstick = data[5] & 0x40 ? 1 : 0;
gamepad->rstick = data[5] & 0x80 ? 1 : 0;
gamepad->dpad_up = data[5] & 0x01 ? 1 : 0;
gamepad->dpad_down = data[5] & 0x02 ? 1 : 0;
gamepad->dpad_left = data[5] & 0x04 ? 1 : 0;
gamepad->dpad_right = data[5] & 0x08 ? 1 : 0;
gamepad->ltrigger = data[6];
gamepad->rtrigger = data[8];
gamepad->lstick_x = * (int16_t *) &data[10];
gamepad->lstick_y = * (int16_t *) &data[12];
gamepad->rstick_x = * (int16_t *) &data[14];
gamepad->rstick_y = * (int16_t *) &data[16];
}
void print_gamepad(const struct gamepad_t *gamepad)
{
printf(" type: 0x%02X\n", gamepad->type);
printf(" const_0: 0x%02X\n", gamepad->const_0);
printf(" id: 0x%02X\n", gamepad->id);
printf(" length: 0x%02X\n", gamepad->length);
printf(" a,b,x,y: %u,%u,%u,%u\n", gamepad->a, gamepad->b, gamepad->x, gamepad->y);
printf(" sync,menu,view: %u,%u,%u\n", gamepad->sync, gamepad->menu, gamepad->view);
printf(" bumper left,right: %u,%u\n", gamepad->lbumper, gamepad->rbumper);
printf(" stick left,right: %u,%u\n", gamepad->lstick, gamepad->rstick);
printf(" dpad up,down,left,right: %u,%u,%u,%u\n",
gamepad->dpad_up, gamepad->dpad_down, gamepad->dpad_left, gamepad->dpad_right);
printf(" trigger left,right: %u,%u\n", gamepad->ltrigger, gamepad->rtrigger);
printf(" lstick x,y: %d,%d\n", gamepad->lstick_x, gamepad->lstick_y);
printf(" rstick x,y: %d,%d\n", gamepad->rstick_x, gamepad->rstick_y);
}
// Initialize controller (with input)
int init_device(libusb_device_handle *devh)
{
uint8_t data[] = { 0x05, 0x20, 0x00, 0x01, 0x00 };
int actual; // how many bytes were actually transferred
// My device's out endpoint is 2
return libusb_interrupt_transfer(devh, (2 | LIBUSB_ENDPOINT_OUT),
data, sizeof(data), &actual, 0);
}
int rumble(libusb_device_handle *devh, uint8_t left, uint8_t right)
{
uint8_t data[] = {
0x09, // activate rumble
0x00,
0x00,
0x09, // length
0x00,
0x0F,
0x00,
0x00,
left, // low-frequency motor
right, // high-frequency motor
0x10, // on period
0x00, // off period
0x01 // repeat count
};
int actual; // how many bytes were actually transferred
// My device's out endpoint is 2
return libusb_interrupt_transfer(devh, (2 | LIBUSB_ENDPOINT_OUT),
data, sizeof(data), &actual, 0);
}