1 /* This file is part of can2joy.
3 * can2joy is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License 2 as
5 * published by the Free Software Foundation.
7 * can2joy is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
12 * You should have received a copy of the GNU General Public License
13 * along with can2joy. If not, see <http://www.gnu.org/licenses/>.
16 #include <linux/can.h>
17 #include <linux/can/raw.h>
18 #include <linux/input.h>
19 #include <linux/uinput.h>
24 #include <sys/ioctl.h>
26 #include <sys/types.h>
30 #define MIN(x, y) ((x) < (y) ? (x) : (y))
31 #define MAX(x, y) ((x) > (y) ? (x) : (y))
34 static int init_can(char *ifname)
36 struct sockaddr_can addr;
41 fd_can = socket(PF_CAN, SOCK_RAW, CAN_RAW);
47 /* Get CAN interfaces's index by name */
48 strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
49 if (ioctl(fd_can, SIOCGIFINDEX, &ifr) < 0) {
50 perror("SIOCGIFINDEX");
54 /* Bind CAN interface by index */
55 memset(&addr, 0, sizeof(addr));
56 addr.can_family = AF_CAN;
57 addr.can_ifindex = ifr.ifr_ifindex;
58 if (bind(fd_can, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
67 static int init_uinput()
69 struct uinput_user_dev uidev;
73 fd_uinput = open("/dev/uinput", O_WRONLY | O_NONBLOCK);
75 perror("open (/dev/uinput)");
79 /* Register push buttons A, B */
80 ioctl(fd_uinput, UI_SET_EVBIT, EV_KEY);
81 ioctl(fd_uinput, UI_SET_KEYBIT, BTN_TRIGGER);
82 ioctl(fd_uinput, UI_SET_KEYBIT, BTN_THUMB);
84 /* Register absolute axes X, Y */
85 ioctl(fd_uinput, UI_SET_EVBIT, EV_ABS);
86 ioctl(fd_uinput, UI_SET_ABSBIT, ABS_X);
87 ioctl(fd_uinput, UI_SET_ABSBIT, ABS_Y);
89 /* Create a virtual input device ID */
90 memset(&uidev, 0, sizeof(uidev));
91 strncpy(uidev.name, "can2joy", UINPUT_MAX_NAME_SIZE);
92 uidev.id.bustype = BUS_USB;
93 uidev.id.vendor = 0x1234;
94 uidev.id.product = 0xfedc;
96 write(fd_uinput, &uidev, sizeof(uidev));
98 /* Set min/max values for axes */
99 uidev.absmin[ABS_X] = 255;
100 uidev.absmax[ABS_X] = -256;
101 uidev.absmin[ABS_Y] = -1;
102 uidev.absmax[ABS_Y] = 1;
103 write(fd_uinput, &uidev, sizeof(uidev));
106 ioctl(fd_uinput, UI_DEV_CREATE);
113 static void receive_one(int fd_can, int fd_uinput)
115 struct can_frame frm;
116 struct sockaddr_can addr;
119 struct input_event ev;
122 memset(&ev, 0, sizeof(ev));
124 ret = recvfrom(fd_can, &frm, sizeof(struct can_frame), 0,
125 (struct sockaddr *)&addr, &len);
133 /* Check clutch and brake pedal.
134 * We only read one bit for each, so don't expect fine
135 * control of your simulated Lamborghini!
139 /* Brake sets bits 0 and 1 (value 3) in byte 4 */
140 ev.code = BTN_TRIGGER;
141 ev.value = !(!(frm.data[4] & 3));
142 write(fd_uinput, &ev, sizeof(ev));
144 /* Clutch sets bit 2 (value 4) in byte 6 */
146 ev.value = !(!(frm.data[6] & 4));
147 write(fd_uinput, &ev, sizeof(ev));
151 /* Translate absolute wheel position.
152 * It's a signed 16-bit integer in the first two bytes
153 * of a 0x3c3 frame, indicating how far it is turned.
154 * Zero means we're driving straight.
155 * The next two bytes are the angular speed of the wheel
156 * being turned, but we don't care about that here.
158 wheel_pos = *((short*)(&frm.data[0]));
159 printf("Wheel position: %i\n", wheel_pos);
161 /* Clamp the wheel position around the zero point.
162 * This is to avoid excessive wear of the wheels of the
163 * parked car as well as of the whole steering mechanism.
165 if (wheel_pos >= 0) {
166 wheel_pos = MIN(255, wheel_pos);
168 /* The first negative value next to zero is
169 * -32768. So we have to invert this to -1
170 * instead of -32768, -2 instead of -32767, etc.
172 wheel_pos = 0 - (wheel_pos + 32768);
173 wheel_pos = MAX(-256, wheel_pos);
175 printf("Wheel position (clamped): %i\n", wheel_pos);
177 /* Report the change in wheel position as the X axis */
180 ev.value = wheel_pos;
181 ret = write(fd_uinput, &ev, sizeof(ev));
183 /* Report a dummy Y axis for programs that expect it */
186 ret = write(fd_uinput, &ev, sizeof(ev));
190 /* Flush the uinput events we just generated */
192 ev.code = SYN_REPORT;
194 write(fd_uinput, &ev, sizeof(ev));
200 int main(int argc, char **argv)
206 printf("Usage: %s <can-interface>\n", argv[0]);
208 printf("Example: %s can0\n", argv[0]);
213 fd_can = init_can(argv[1]);
217 fd_uinput = init_uinput();
223 receive_one(fd_can, fd_uinput);
226 ioctl(fd_uinput, UI_DEV_DESTROY);