-
Notifications
You must be signed in to change notification settings - Fork 0
/
wbb-uinput.c
147 lines (123 loc) · 3.17 KB
/
wbb-uinput.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
/*
* Creates a controller with the inputs of the Wii Balance Board
* No drivers or other programs needed!!!
*
* Connect the Wii Balance Board via Bluetooth
* If the blue light stays on it's connected
* Use ls /dev/input to find out which one the board is
* It should be the /dev/input/event* with the highest number
* Compile and run this file with the path specified in stdin
* Use antimicrox or other programs to configure the inputs
*
* Modified code from https://github.com/keldu/WiiWeight
* and https://github.com/GrantEdwards/uinput-joystick-demo
*/
#include <fcntl.h>
#include <linux/uinput.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
void setWeight(int co, int val);
static void setup_abs(int fdw, unsigned chan, int min, int max);
static int x, y;
struct weight_values
{
int fr, fl, br, bl;
} weight;
int bytes;
void setWeight(int co, int val)
{
switch(co){
case ABS_HAT0X: weight.fr = val; break;
case ABS_HAT1X: weight.fl = val; break;
case ABS_HAT0Y: weight.br = val; break;
case ABS_HAT1Y: weight.bl = val; break;
}
x=((weight.fr+weight.br)-(weight.fl+weight.bl))*1; /* set x axis multiplier */
y=((weight.bl+weight.br)-(weight.fl+weight.fr))*1; /* set y axis multiplier */
}
int main(int argc, char** argv)
{
char* input_device=NULL;
int fdr;
input_device=argv[1];
fdr=open(input_device, O_RDONLY);
struct input_event evr;
struct input_event evw[3];
memset(&evr, 0, sizeof(evr));
memset(&evw, 0, sizeof(evw));
if (argc < 2){
printf("Missing device path! Specify path. /dev/input/event*\n");
return 1;
}
if (fdr < 0){
perror("Failed to read device! Correct path?\n");
return 1;
}
int fdw = open("/dev/uinput", O_WRONLY | O_NONBLOCK);
if (fdw < 0) {
perror("can not open /dev/uinput");
return 1;
}
ioctl(fdw, UI_SET_EVBIT, EV_ABS);
setup_abs(fdw, ABS_X, -8192, 8192); //possible steps. affects axis scaling
setup_abs(fdw, ABS_Y, -8192, 8192); //possible steps. affects axis scaling
setup_abs(fdw, ABS_Z, -32767, 32767); //default values for joysticks
struct uinput_setup setup = {
.name = "wbb",
.id = {
.bustype = BUS_USB,
.vendor = 0x3,
.product = 0x3,
.version = 2,
}
};
if (ioctl(fdw, UI_DEV_SETUP, &setup)) {
perror("UI_DEV_SETUP");
return 1;
}
if (ioctl(fdw, UI_DEV_CREATE)) {
perror("UI_DEV_CREATE");
return 1;
}
while (1) {
bytes = read(fdr, &evr, sizeof(struct input_event));
if (evr.type == EV_ABS){
setWeight(evr.code, evr.value);
printf("x %d\ny %d\n", x, y); /* not needed */
}
evw[0].type = EV_ABS;
evw[0].code = ABS_Y;
evw[0].value = y;
evw[1].type = EV_ABS;
evw[1].code = ABS_X;
evw[1].value = x;
evw[2].type = EV_SYN;
evw[2].code = SYN_REPORT;
evw[2].value = 0;
if (write(fdw, &evw, sizeof(evw)) < 0) {
perror("can not write");
return 1;
}
}
if (ioctl(fdw, UI_DEV_DESTROY)) {
perror("UI_DEV_DESTROY");
return 1;
}
close(fdw);
return 0;
}
static void setup_abs(int fd, unsigned chan, int min, int max)
{
if (ioctl(fd, UI_SET_ABSBIT, chan))
perror("UI_SET_ABSBIT");
struct uinput_abs_setup s = {
.code = chan,
.absinfo = {
.minimum = min,
.maximum = max
}
};
if (ioctl(fd, UI_ABS_SETUP, &s))
perror("UI_ABS_SETUP");
}