root/wminput/uinput.c

Revision 2100f14c612471084434b364501e3818c7f4144e, 7.1 kB (checked in by L. Donnie Smith <donnie.smith@…>, 3 years ago)

Various administrative updates

change email addresses
remove individual file changelogs (that's what version control is for)

  • Property mode set to 100644
Line 
1/* Copyright (C) 2007 L. Donnie Smith <donnie.smith@gatech.edu>
2 *
3 *  This program is free software; you can redistribute it and/or modify
4 *  it under the terms of the GNU General Public License as published by
5 *  the Free Software Foundation; either version 2 of the License, or
6 *  (at your option) any later version.
7 *
8 *  This program is distributed in the hope that it will be useful,
9 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
10 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 *  GNU General Public License for more details.
12 *
13 *  You should have received a copy of the GNU General Public License
14 *  along with this program; if not, write to the Free Software
15 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
16 *
17 */
18
19#include <stdint.h>
20#include <string.h>
21
22#include <fcntl.h>
23#include <sys/ioctl.h>
24#include <sys/types.h>
25#include <unistd.h>
26
27#include <linux/input.h>
28#include <linux/uinput.h>
29
30#include "conf.h"
31#include "util.h"
32
33/* UInput */
34char *uinput_filename[] = {"/dev/uinput", "/dev/input/uinput",
35                           "/dev/misc/uinput"};
36#define UINPUT_FILENAME_COUNT (sizeof(uinput_filename)/sizeof(char *))
37
38int uinput_open(struct conf *conf)
39{
40        unsigned int i;
41        int j;
42        int request;
43
44        /* Open uinput device */
45        for (i=0; i < UINPUT_FILENAME_COUNT; i++) {
46                if ((conf->fd = open(uinput_filename[i], O_RDWR)) >= 0) {
47                        break;
48                }
49        }
50        if (conf->fd < 0) {
51                wminput_err("unable to open uinput");
52                return -1;
53        }
54
55        if (write(conf->fd, &conf->dev, sizeof conf->dev) != sizeof conf->dev) {
56                wminput_err("error on uinput device setup");
57                close(conf->fd);
58                return -1;
59        }
60
61        if (conf->ff) {
62                if (ioctl(conf->fd, UI_SET_EVBIT, EV_FF) < 0) {
63                        wminput_err("error on uinput ioctl");
64                        close(conf->fd);
65                        return -1;
66                }
67                if (ioctl(conf->fd, UI_SET_FFBIT, FF_RUMBLE) < 0) {
68                        wminput_err("error on uinput ioctl");
69                        close(conf->fd);
70                        return -1;
71                }
72        }
73
74        if (ioctl(conf->fd, UI_SET_EVBIT, EV_KEY) < 0) {
75                wminput_err("error on uinput ioctl");
76                close(conf->fd);
77                return -1;
78        }       
79
80        for (i=0; i < CONF_WM_BTN_COUNT; i++) {
81                if (conf->wiimote_bmap[i].active) {
82                        if (ioctl(conf->fd, UI_SET_KEYBIT, conf->wiimote_bmap[i].action)
83                          < 0) {
84                                wminput_err("error on uinput ioctl");
85                                close(conf->fd);
86                                return -1;
87                        }
88                }                       
89        }
90        for (i=0; i < CONF_NC_BTN_COUNT; i++) {
91                if (conf->nunchuk_bmap[i].active) {
92                        if (ioctl(conf->fd, UI_SET_KEYBIT, conf->nunchuk_bmap[i].action)
93                          < 0) {
94                                wminput_err("error on uinput ioctl");
95                                close(conf->fd);
96                                return -1;
97                        }
98                }                       
99        }
100        for (i=0; i < CONF_CC_BTN_COUNT; i++) {
101                if (conf->classic_bmap[i].active) {
102                        if (ioctl(conf->fd, UI_SET_KEYBIT, conf->classic_bmap[i].action)
103                          < 0) {
104                                wminput_err("error on uinput ioctl");
105                                close(conf->fd);
106                                return -1;
107                        }
108                }                       
109        }
110        for (i=0; i < CONF_AXIS_COUNT; i++) {
111                if (conf->amap[i].active) {
112                        if (ioctl(conf->fd, UI_SET_EVBIT, conf->amap[i].axis_type) < 0) {
113                                wminput_err("error uinput ioctl");
114                                close(conf->fd);
115                                return -1;
116                        }
117                        request = (conf->amap[i].axis_type == EV_ABS) ? UI_SET_ABSBIT
118                                                                      : UI_SET_RELBIT;
119                        if (ioctl(conf->fd, request, conf->amap[i].action) < 0) {
120                                wminput_err("error uinput ioctl");
121                                close(conf->fd);
122                                return -1;
123                        }
124                        if ((conf->amap[i].flags & CONF_POINTER) &&
125                          (conf->amap[i].axis_type == EV_ABS) &&
126                          ((conf->amap[i].action == ABS_X) ||
127                           (conf->amap[i].action == ABS_Y) ||
128                           (conf->amap[i].action == ABS_Z))) {
129                                if (ioctl(conf->fd, UI_SET_EVBIT, EV_REL) < 0) {
130                                        wminput_err("error uinput ioctl");
131                                        close(conf->fd);
132                                        return -1;
133                                }
134                                if (ioctl(conf->fd, UI_SET_RELBIT, conf->amap[i].action) < 0) {
135                                        wminput_err("error uinput ioctl");
136                                        close(conf->fd);
137                                        return -1;
138                                }
139                        }
140                }
141        }
142        for (i=0; i < CONF_MAX_PLUGINS; i++) {
143                if (conf->plugins[i].name) {
144                        for (j=0; j < conf->plugins[i].info->button_count; j++) {
145                                if (conf->plugins[i].bmap[j].active) {
146                                        if (ioctl(conf->fd, UI_SET_KEYBIT,
147                                                  conf->plugins[i].bmap[j].action) < 0) {
148                                                wminput_err("error on uinput ioctl");
149                                                close(conf->fd);
150                                                return -1;
151                                        }
152                                }
153                        }
154                        for (j=0; j < conf->plugins[i].info->axis_count; j++) {
155                                if (conf->plugins[i].amap[j].active) {
156                                        if (ioctl(conf->fd, UI_SET_EVBIT,
157                                                  conf->plugins[i].amap[j].axis_type) < 0) {
158                                                wminput_err("error uinput ioctl");
159                                                close(conf->fd);
160                                                return -1;
161                                        }
162                                        request = (conf->plugins[i].amap[j].axis_type == EV_ABS)
163                                                  ? UI_SET_ABSBIT
164                                                  : UI_SET_RELBIT;
165                                        if (ioctl(conf->fd, request,
166                                                  conf->plugins[i].amap[j].action) < 0) {
167                                                wminput_err("error uinput ioctl");
168                                                close(conf->fd);
169                                                return -1;
170                                        }
171                                        if ((conf->plugins[i].amap[j].flags & CONF_POINTER) &&
172                                          (conf->plugins[i].amap[j].axis_type == EV_ABS) &&
173                                          ((conf->plugins[i].amap[j].action == ABS_X) ||
174                                           (conf->plugins[i].amap[j].action == ABS_Y) ||
175                                           (conf->plugins[i].amap[j].action == ABS_Z))) {
176                                                if (ioctl(conf->fd, UI_SET_EVBIT, EV_REL) < 0) {
177                                                        wminput_err("error uinput ioctl");
178                                                        close(conf->fd);
179                                                        return -1;
180                                                }
181                                                if (ioctl(conf->fd, UI_SET_RELBIT,
182                                                          conf->plugins[i].amap[j].action) < 0) {
183                                                        wminput_err("error uinput ioctl");
184                                                        close(conf->fd);
185                                                        return -1;
186                                                }
187                                        }
188                                }
189                        }
190                }
191        }               
192
193        if (ioctl(conf->fd, UI_DEV_CREATE) < 0) {
194                wminput_err("Error on uinput dev create");
195                close(conf->fd);
196                return -1;
197        }
198
199        return 0;
200}
201
202int uinput_close(struct conf *conf)
203{
204        if (close(conf->fd)) {
205                wminput_err("Error on uinput close");
206                return -1;
207        }
208
209        return 0;
210}
211
212int send_event(struct conf *conf, __u16 type, __u16 code, __s32 value)
213{
214        struct input_event event;
215
216        memset(&event, 0, sizeof(event));
217        event.type = type;
218        event.code = code;
219        event.value = value;
220
221        if (write(conf->fd, &event, sizeof(event)) != sizeof(event)) {
222                wminput_err("Error on send_event");
223                return -1;
224        }
225
226        return 0;
227}
228
229void *uinput_listen(struct uinput_listen_data *data)
230{
231        size_t len;
232        struct input_event event;
233        struct uinput_ff_upload upload;
234        struct uinput_ff_erase erase;
235
236        do {
237                if ((len = read(data->conf->fd, &event, sizeof event)) !=
238                  sizeof event) {
239                        wminput_err("Error on uinput read");
240                        continue;
241                }
242
243                switch (event.type) {
244                case EV_UINPUT:
245                        switch (event.code) {
246                        case UI_FF_UPLOAD:
247                                erase.request_id = event.value;
248                                if (ioctl(data->conf->fd, UI_BEGIN_FF_UPLOAD, &upload) < 0) {
249                                        wminput_err("Error on ff upload begin");
250                                }
251                                if (cwiid_set_rumble(data->wiimote, 1)) {
252                                        wminput_err("Error setting rumble");
253                                }
254                                if (ioctl(data->conf->fd, UI_END_FF_UPLOAD, &upload) < 0) {
255                                        wminput_err("Error on ff upload end");
256                                }
257                                break;
258                        case UI_FF_ERASE:
259                                erase.request_id = event.value;
260                                if (ioctl(data->conf->fd, UI_BEGIN_FF_ERASE, &erase) < 0) {
261                                        wminput_err("Error on ff erase begin");
262                                }
263                                if (cwiid_set_rumble(data->wiimote, 0)) {
264                                        wminput_err("Error clearing rumble");
265                                }
266                                if (ioctl(data->conf->fd, UI_END_FF_ERASE, &erase) < 0) {
267                                        wminput_err("Error on ff erase end");
268                                }
269                                break;
270                        default:
271                                break;
272                        }
273                        break;
274                default:
275                        break;
276                }
277        } while (-1);
278}
Note: See TracBrowser for help on using the browser.