root/branches/dev/wminput/uinput.c

Revision 118, 7.6 kB (checked in by dsmith, 2 years ago)

Create dev branch (currently contains experimental python plugins)

Line 
1 /* Copyright (C) 2007 L. Donnie Smith <wiimote@abstrakraft.org>
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  *  ChangeLog:
18  *  2007-05-16 L. Donnie Smith <cwiid@abstrakraft.org>
19  *  * changed cwiid_{connect,disconnect,command} to
20  *    cwiid_{open,close,request_status|set_led|set_rumble|set_rpt_mode}
21  *
22  *  2007-04-09 L. Donnie Smith <cwiid@abstrakraft.org>
23  *  * updated for libcwiid rename
24  *
25  *  2007-04-08 L. Donnie Smith <cwiid@anstrakraft.org>
26  *  * fixed signed/unsigned comparison warning in uinput_open
27  *
28  *  2007-03-04 L. Donnie Smith <cwiid@abstrakraft.org>
29  *  * Initial ChangeLog
30  *  * type audit (stdint, const, char booleans)
31  */
32
33 #include <stdint.h>
34 #include <string.h>
35
36 #include <fcntl.h>
37 #include <sys/ioctl.h>
38 #include <sys/types.h>
39 #include <unistd.h>
40
41 #include <linux/input.h>
42 #include <linux/uinput.h>
43
44 #include "conf.h"
45 #include "util.h"
46
47 /* UInput */
48 char *uinput_filename[] = {"/dev/uinput", "/dev/input/uinput",
49                            "/dev/misc/uinput"};
50 #define UINPUT_FILENAME_COUNT (sizeof(uinput_filename)/sizeof(char *))
51
52 int uinput_open(struct conf *conf)
53 {
54         unsigned int i;
55         int j;
56         int request;
57
58         /* Open uinput device */
59         for (i=0; i < UINPUT_FILENAME_COUNT; i++) {
60                 if ((conf->fd = open(uinput_filename[i], O_RDWR)) >= 0) {
61                         break;
62                 }
63         }
64         if (conf->fd < 0) {
65                 wminput_err("unable to open uinput");
66                 return -1;
67         }
68
69         if (write(conf->fd, &conf->dev, sizeof conf->dev) != sizeof conf->dev) {
70                 wminput_err("error on uinput device setup");
71                 close(conf->fd);
72                 return -1;
73         }
74
75         if (conf->ff) {
76                 if (ioctl(conf->fd, UI_SET_EVBIT, EV_FF) < 0) {
77                         wminput_err("error on uinput ioctl");
78                         close(conf->fd);
79                         return -1;
80                 }
81                 if (ioctl(conf->fd, UI_SET_FFBIT, FF_RUMBLE) < 0) {
82                         wminput_err("error on uinput ioctl");
83                         close(conf->fd);
84                         return -1;
85                 }
86         }
87
88         if (ioctl(conf->fd, UI_SET_EVBIT, EV_KEY) < 0) {
89                 wminput_err("error on uinput ioctl");
90                 close(conf->fd);
91                 return -1;
92         }       
93
94         for (i=0; i < CONF_WM_BTN_COUNT; i++) {
95                 if (conf->wiimote_bmap[i].active) {
96                         if (ioctl(conf->fd, UI_SET_KEYBIT, conf->wiimote_bmap[i].action)
97                           < 0) {
98                                 wminput_err("error on uinput ioctl");
99                                 close(conf->fd);
100                                 return -1;
101                         }
102                 }                       
103         }
104         for (i=0; i < CONF_NC_BTN_COUNT; i++) {
105                 if (conf->nunchuk_bmap[i].active) {
106                         if (ioctl(conf->fd, UI_SET_KEYBIT, conf->nunchuk_bmap[i].action)
107                           < 0) {
108                                 wminput_err("error on uinput ioctl");
109                                 close(conf->fd);
110                                 return -1;
111                         }
112                 }                       
113         }
114         for (i=0; i < CONF_CC_BTN_COUNT; i++) {
115                 if (conf->classic_bmap[i].active) {
116                         if (ioctl(conf->fd, UI_SET_KEYBIT, conf->classic_bmap[i].action)
117                           < 0) {
118                                 wminput_err("error on uinput ioctl");
119                                 close(conf->fd);
120                                 return -1;
121                         }
122                 }                       
123         }
124         for (i=0; i < CONF_AXIS_COUNT; i++) {
125                 if (conf->amap[i].active) {
126                         if (ioctl(conf->fd, UI_SET_EVBIT, conf->amap[i].axis_type) < 0) {
127                                 wminput_err("error uinput ioctl");
128                                 close(conf->fd);
129                                 return -1;
130                         }
131                         request = (conf->amap[i].axis_type == EV_ABS) ? UI_SET_ABSBIT
132                                                                       : UI_SET_RELBIT;
133                         if (ioctl(conf->fd, request, conf->amap[i].action) < 0) {
134                                 wminput_err("error uinput ioctl");
135                                 close(conf->fd);
136                                 return -1;
137                         }
138                         if ((conf->amap[i].flags & CONF_POINTER) &&
139                           (conf->amap[i].axis_type == EV_ABS) &&
140                           ((conf->amap[i].action == ABS_X) ||
141                            (conf->amap[i].action == ABS_Y) ||
142                            (conf->amap[i].action == ABS_Z))) {
143                                 if (ioctl(conf->fd, UI_SET_EVBIT, EV_REL) < 0) {
144                                         wminput_err("error uinput ioctl");
145                                         close(conf->fd);
146                                         return -1;
147                                 }
148                                 if (ioctl(conf->fd, UI_SET_RELBIT, conf->amap[i].action) < 0) {
149                                         wminput_err("error uinput ioctl");
150                                         close(conf->fd);
151                                         return -1;
152                                 }
153                         }
154                 }
155         }
156         for (i=0; i < CONF_MAX_PLUGINS; i++) {
157                 if (conf->plugins[i].name) {
158                         for (j=0; j < conf->plugins[i].info->button_count; j++) {
159                                 if (conf->plugins[i].bmap[j].active) {
160                                         if (ioctl(conf->fd, UI_SET_KEYBIT,
161                                                   conf->plugins[i].bmap[j].action) < 0) {
162                                                 wminput_err("error on uinput ioctl");
163                                                 close(conf->fd);
164                                                 return -1;
165                                         }
166                                 }
167                         }
168                         for (j=0; j < conf->plugins[i].info->axis_count; j++) {
169                                 if (conf->plugins[i].amap[j].active) {
170                                         if (ioctl(conf->fd, UI_SET_EVBIT,
171                                                   conf->plugins[i].amap[j].axis_type) < 0) {
172                                                 wminput_err("error uinput ioctl");
173                                                 close(conf->fd);
174                                                 return -1;
175                                         }
176                                         request = (conf->plugins[i].amap[j].axis_type == EV_ABS)
177                                                   ? UI_SET_ABSBIT
178                                                   : UI_SET_RELBIT;
179                                         if (ioctl(conf->fd, request,
180                                                   conf->plugins[i].amap[j].action) < 0) {
181                                                 wminput_err("error uinput ioctl");
182                                                 close(conf->fd);
183                                                 return -1;
184                                         }
185                                         if ((conf->plugins[i].amap[j].flags & CONF_POINTER) &&
186                                           (conf->plugins[i].amap[j].axis_type == EV_ABS) &&
187                                           ((conf->plugins[i].amap[j].action == ABS_X) ||
188                                            (conf->plugins[i].amap[j].action == ABS_Y) ||
189                                            (conf->plugins[i].amap[j].action == ABS_Z))) {
190                                                 if (ioctl(conf->fd, UI_SET_EVBIT, EV_REL) < 0) {
191                                                         wminput_err("error uinput ioctl");
192                                                         close(conf->fd);
193                                                         return -1;
194                                                 }
195                                                 if (ioctl(conf->fd, UI_SET_RELBIT,
196                                                           conf->plugins[i].amap[j].action) < 0) {
197                                                         wminput_err("error uinput ioctl");
198                                                         close(conf->fd);
199                                                         return -1;
200                                                 }
201                                         }
202                                 }
203                         }
204                 }
205         }               
206
207         if (ioctl(conf->fd, UI_DEV_CREATE) < 0) {
208                 wminput_err("Error on uinput dev create");
209                 close(conf->fd);
210                 return -1;
211         }
212
213         return 0;
214 }
215
216 int uinput_close(struct conf *conf)
217 {
218         if (close(conf->fd)) {
219                 wminput_err("Error on uinput close");
220                 return -1;
221         }
222
223         return 0;
224 }
225
226 int send_event(struct conf *conf, __u16 type, __u16 code, __s32 value)
227 {
228         struct input_event event;
229
230         memset(&event, 0, sizeof(event));
231         event.type = type;
232         event.code = code;
233         event.value = value;
234
235         if (write(conf->fd, &event, sizeof(event)) != sizeof(event)) {
236                 wminput_err("Error on send_event");
237                 return -1;
238         }
239
240         return 0;
241 }
242
243 void *uinput_listen(struct uinput_listen_data *data)
244 {
245         size_t len;
246         struct input_event event;
247         struct uinput_ff_upload upload;
248         struct uinput_ff_erase erase;
249
250         do {
251                 if ((len = read(data->conf->fd, &event, sizeof event)) !=
252                   sizeof event) {
253                         wminput_err("Error on uinput read");
254                         continue;
255                 }
256
257                 switch (event.type) {
258                 case EV_UINPUT:
259                         switch (event.code) {
260                         case UI_FF_UPLOAD:
261                                 erase.request_id = event.value;
262                                 if (ioctl(data->conf->fd, UI_BEGIN_FF_UPLOAD, &upload) < 0) {
263                                         wminput_err("Error on ff upload begin");
264                                 }
265                                 if (cwiid_set_rumble(data->wiimote, 1)) {
266                                         wminput_err("Error setting rumble");
267                                 }
268                                 if (ioctl(data->conf->fd, UI_END_FF_UPLOAD, &upload) < 0) {
269                                         wminput_err("Error on ff upload end");
270                                 }
271                                 break;
272                         case UI_FF_ERASE:
273                                 erase.request_id = event.value;
274                                 if (ioctl(data->conf->fd, UI_BEGIN_FF_ERASE, &erase) < 0) {
275                                         wminput_err("Error on ff erase begin");
276                                 }
277                                 if (cwiid_set_rumble(data->wiimote, 0)) {
278                                         wminput_err("Error clearing rumble");
279                                 }
280                                 if (ioctl(data->conf->fd, UI_END_FF_ERASE, &erase) < 0) {
281                                         wminput_err("Error on ff erase end");
282                                 }
283                                 break;
284                         default:
285                                 break;
286                         }
287                         break;
288                 default:
289                         break;
290                 }
291         } while (-1);
292 }
Note: See TracBrowser for help on using the browser.