Initial import
[can2joy.git] / can2joy.c
1 #include <fcntl.h>
2 #include <linux/can.h>
3 #include <linux/can/raw.h>
4 #include <linux/input.h>
5 #include <linux/uinput.h>
6 #include <net/if.h>
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <string.h>
10 #include <sys/ioctl.h>
11 #include <sys/stat.h>
12 #include <sys/types.h>
13 #include <unistd.h>
14
15
16 #define MIN(x, y) ((x) < (y) ? (x) : (y))
17 #define MAX(x, y) ((x) > (y) ? (x) : (y))
18
19
20 static int init_can(char *ifname)
21 {
22         struct sockaddr_can addr;
23         struct ifreq ifr;
24         int fd_can;
25
26         /* Open CAN socket */
27         fd_can = socket(PF_CAN, SOCK_RAW, CAN_RAW);
28         if (fd_can < 0) {
29                 perror("socket");
30                 return fd_can;
31         }
32
33         /* Get CAN interfaces's index by name */
34         strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
35         if (ioctl(fd_can, SIOCGIFINDEX, &ifr) < 0) {
36                 perror("SIOCGIFINDEX");
37                 return -1;
38         }
39
40         /* Bind CAN interface by index */
41         memset(&addr, 0, sizeof(addr));
42         addr.can_family = AF_CAN;
43         addr.can_ifindex = ifr.ifr_ifindex;
44         if (bind(fd_can, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
45                 perror("bind");
46                 return -1;
47         }
48
49         return fd_can;
50 }
51
52
53 static int init_uinput()
54 {
55         struct uinput_user_dev uidev;
56         int fd_uinput;
57
58         /* Open uinput */
59         fd_uinput = open("/dev/uinput", O_WRONLY | O_NONBLOCK);
60         if(fd_uinput < 0) {
61                 perror("open (/dev/uinput)");
62                 return fd_uinput;
63         }
64
65         /* Register push buttons A, B */
66         ioctl(fd_uinput, UI_SET_EVBIT, EV_KEY);
67         ioctl(fd_uinput, UI_SET_KEYBIT, BTN_TRIGGER);
68         ioctl(fd_uinput, UI_SET_KEYBIT, BTN_THUMB);
69
70         /* Register absolute axes X, Y */
71         ioctl(fd_uinput, UI_SET_EVBIT, EV_ABS);
72         ioctl(fd_uinput, UI_SET_ABSBIT, ABS_X);
73         ioctl(fd_uinput, UI_SET_ABSBIT, ABS_Y);
74
75         /* Create a virtual input device ID */
76         memset(&uidev, 0, sizeof(uidev));
77         strncpy(uidev.name, "can2joy", UINPUT_MAX_NAME_SIZE);
78         uidev.id.bustype = BUS_USB;
79         uidev.id.vendor  = 0x1234;
80         uidev.id.product = 0xfedc;
81         uidev.id.version = 1;
82         write(fd_uinput, &uidev, sizeof(uidev));
83
84         /* Set min/max values for axes */
85         uidev.absmin[ABS_X] = 255;
86         uidev.absmax[ABS_X] = -256;
87         uidev.absmin[ABS_Y] = -1;
88         uidev.absmax[ABS_Y] = 1;
89         write(fd_uinput, &uidev, sizeof(uidev));
90
91         /* Let uinput rip */
92         ioctl(fd_uinput, UI_DEV_CREATE);
93
94         return fd_uinput;
95 }
96
97
98
99 static void receive_one(int fd_can, int fd_uinput)
100 {
101         struct can_frame frm;
102         struct sockaddr_can addr;
103         int ret;
104         socklen_t len;
105         struct input_event ev;
106         short wheel_pos;
107
108         memset(&ev, 0, sizeof(ev));
109
110         ret = recvfrom(fd_can, &frm, sizeof(struct can_frame), 0,
111         (struct sockaddr *)&addr, &len);
112         if (ret < 0) {
113         perror("recvfrom");
114         exit(1);
115         }
116
117         switch(frm.can_id) {
118         case 0x35b:
119                 /* Check clutch and brake pedal.
120                  * We only read one bit for each, so don't expect fine
121                  * control of your simulated Lamborghini!
122                  */
123                 ev.type = EV_KEY;
124                 ev.code = BTN_TRIGGER;
125                 ev.value = !(!(frm.data[4] & 3));
126                 write(fd_uinput, &ev, sizeof(ev));
127
128                 ev.code = BTN_THUMB;
129                 ev.value = !(!(frm.data[6] & 4));
130                 write(fd_uinput, &ev, sizeof(ev));
131                 break;
132
133         case 0x3c3:
134                 /* Translate absolute wheel position.
135                  * It's a signed 16-bit integer in the first two bytes
136                  * of a 0x3c3 frame, indicating how far it is turned.
137                  * Zero means we're driving straight.
138                  * The next two bytes are the angular speed of the wheel
139                  * being turned, but we don't care about that here.
140                  */
141                 wheel_pos = *((short*)(&frm.data[0]));
142                 printf("Wheel position: %i\n", wheel_pos);
143
144                 /* Clamp the wheel position around the zero point.
145                  * This is to avoid excessive wear of the wheels of the
146                  * parked car as well as of the whole steering mechanism.
147                  */
148                 if (wheel_pos >= 0) {
149                         wheel_pos = MIN(255, wheel_pos);
150                 } else {
151                         /* The first negative value next to zero is
152                          * -32768. So we have to invert this to -1
153                          * instead of -32768, -2 instead of -32767, etc.
154                          */
155                         wheel_pos = 0 - (wheel_pos + 32768);
156                         wheel_pos = MAX(-256, wheel_pos);
157                 }
158                 printf("Wheel position (clamped): %i\n", wheel_pos);
159
160                 /* Report the change in wheel position as the X axis */
161                 ev.type = EV_ABS;
162                 ev.code = ABS_X;
163                 ev.value = wheel_pos;
164                 ret = write(fd_uinput, &ev, sizeof(ev));
165
166                 /* Report a dummy Y axis for programs that expect it */
167                 ev.code = ABS_Y;
168                 ev.value = 0;
169                 ret = write(fd_uinput, &ev, sizeof(ev));
170                 break;
171         }
172
173         /* Flush the uinput events we just generated */
174         ev.type = EV_SYN;
175         ev.code = SYN_REPORT;
176         ev.value = 0;
177         write(fd_uinput, &ev, sizeof(ev));
178 }
179
180
181
182
183 int main(int argc, char **argv)
184 {
185         int fd_can;
186         int fd_uinput;
187
188         if (argc < 2) {
189                 printf("Usage: %s <can-interface>\n", argv[0]);
190                 printf("\n");
191                 printf("Example: %s can0\n", argv[0]);
192                 return 1;
193         }
194
195
196         fd_can = init_can(argv[1]);
197         if (fd_can < 0)
198                 return 1;
199
200         fd_uinput = init_uinput();
201         if (fd_uinput < 0)
202                 return 1;
203
204
205         for (;;)
206                 receive_one(fd_can, fd_uinput);
207
208
209         ioctl(fd_uinput, UI_DEV_DESTROY);
210
211         return 0;
212 }