root/wminput/main.c @ d372b079b501b1fea934c990aaaed85fde5571f2

Revision d372b079b501b1fea934c990aaaed85fde5571f2, 14.2 KB (checked in by dsmith <dsmith@…>, 6 years ago)

wminput: add filenames and proper location tracking to parser error messages

git-svn-id: http://abstrakraft.org/cwiid/svn/trunk@18 918edb2d-ff29-0410-9de2-eb38e7f22bc7

  • Property mode set to 100644
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
18#include <stdio.h>
19#include <stdlib.h>
20
21#include <pthread.h>
22#include <signal.h>
23#include <unistd.h>
24
25#include <wiimote.h>
26
27#include "conf.h"
28#include "util.h"
29#include "wmplugin.h"
30
31struct conf conf;
32
33/* GetOpt */
34#define OPTSTRING       "hc:"
35extern char *optarg;
36extern int optind, opterr, optopt;
37
38/* Prototypes */
39wiimote_mesg_callback_t wiimote_callback;
40int wminput_set_report_mode();
41void process_btn_mesg(struct wiimote_btn_mesg *mesg);
42void process_nunchuk_mesg(struct wiimote_nunchuk_mesg *mesg);
43void process_classic_mesg(struct wiimote_classic_mesg *mesg);
44void process_plugin(struct plugin *, int, union wiimote_mesg * []);
45
46/* Globals */
47wiimote_t *wiimote;
48int init;
49
50#define DEFAULT_CONFIG_FILE     "default"
51
52#define USAGE "usage:%s [-h] [-c config] [bdaddr]\n"
53
54#define HOME_DIR_LEN    128
55int main(int argc, char *argv[])
56{
57        char *config_search_dirs[3], *plugin_search_dirs[3];
58        char *config_filename = DEFAULT_CONFIG_FILE;
59        char home_config_dir[HOME_DIR_LEN];
60        char home_plugin_dir[HOME_DIR_LEN];
61        char *tmp;
62        int c, i;
63        char *str_addr;
64        bdaddr_t bdaddr;
65        sigset_t sigset;
66        int signum, ret=0;
67        struct uinput_listen_data uinput_listen_data;
68        pthread_t uinput_listen_thread;
69
70        init = -1;
71
72        /* Parse Options */
73        while ((c = getopt(argc, argv, OPTSTRING)) != -1) {
74                switch (c) {
75                case 'h':
76                        printf(USAGE, argv[0]);
77                        return 0;
78                        break;
79                case 'c':
80                        config_filename = optarg;
81                        break;
82                case '?':
83                default:
84                        wminput_err("unknown command-line option: -%c", c);
85                        break;
86                }
87        }
88
89        /* Load Config */
90        if ((tmp = getenv("HOME")) == NULL) {
91                wminput_err("unable to find home directory");
92                config_search_dirs[0] = WMINPUT_CONFIG_DIR;
93                plugin_search_dirs[0] = CWIID_PLUGINS_DIR;
94                config_search_dirs[1] = plugin_search_dirs[1] = NULL;
95        }
96        else {
97                snprintf(home_config_dir, HOME_DIR_LEN, "%s/.cwiid/wminput", tmp);
98                snprintf(home_plugin_dir, HOME_DIR_LEN, "%s/.cwiid/plugins", tmp);
99                config_search_dirs[0] = home_config_dir;
100                plugin_search_dirs[0] = home_plugin_dir;
101                config_search_dirs[1] = WMINPUT_CONFIG_DIR;
102                plugin_search_dirs[1] = CWIID_PLUGINS_DIR;
103                config_search_dirs[2] = plugin_search_dirs[2] = NULL;
104        }
105
106        if (conf_load(&conf, config_filename, config_search_dirs,
107          plugin_search_dirs)) {
108                return -1;
109        }
110
111        /* BDADDR */
112        if (optind < argc) {
113                if (str2ba(argv[optind], &bdaddr)) {
114                        wminput_err("invalid bdaddr");
115                        bdaddr = *BDADDR_ANY;
116                }
117                optind++;
118                if (optind < argc) {
119                        wminput_err("invalid command-line");
120                        printf(USAGE, argv[0]);
121                        conf_unload(&conf);
122                        return -1;
123                }
124        }
125        else if ((str_addr = getenv(WIIMOTE_BDADDR)) != NULL) {
126                if (str2ba(str_addr, &bdaddr)) {
127                        wminput_err("invalid address in %s", WIIMOTE_BDADDR);
128                        bdaddr = *BDADDR_ANY;
129                }
130        }
131        else {
132                bdaddr = *BDADDR_ANY;
133        }
134
135        /* Wiimote connect */
136        printf("Put Wiimote in discoverable mode now (press 1+2)...\n");
137        if ((wiimote = wiimote_connect(bdaddr, wiimote_callback, NULL)) == NULL) {
138                wminput_err("unable to connect");
139                conf_unload(&conf);
140                return -1;
141        }
142
143        /* init plugins */
144        for (i=0; (i < CONF_MAX_PLUGINS) && conf.plugins[i].name; i++) {
145                if ((*conf.plugins[i].init)(i, wiimote)) {
146                        wminput_err("error on %s init", conf.plugins[i].name);
147                        conf_unload(&conf);
148                        wiimote_disconnect(wiimote);
149                        return -1;
150                }
151        }
152
153        if (wminput_set_report_mode()) {
154                conf_unload(&conf);
155                wiimote_disconnect(wiimote);
156                return -1;
157        }
158
159        uinput_listen_data.wiimote = wiimote;
160        uinput_listen_data.conf = &conf;
161        if (pthread_create(&uinput_listen_thread, NULL,
162                           (void *(*)(void *))uinput_listen,
163                           &uinput_listen_data)) {
164                wminput_err("error starting uinput listen thread");
165                conf_unload(&conf);
166                wiimote_disconnect(wiimote);
167                return -1;
168        }
169
170
171        printf("Ready.\n");
172
173        init = 0;
174
175        /* wait */
176        sigemptyset(&sigset);
177        sigaddset(&sigset, SIGTERM);
178        sigaddset(&sigset, SIGINT);
179        sigprocmask(SIG_BLOCK, &sigset, NULL);
180        sigwait(&sigset, &signum);
181
182        printf("Exiting.\n");
183
184        if (pthread_cancel(uinput_listen_thread)) {
185                wminput_err("error canceling uinput listen thread");
186                ret = -1;
187        }
188        else if (pthread_join(uinput_listen_thread, NULL)) {
189                wminput_err("error joing uinput listen thread");
190                ret = -1;
191        }
192
193        /* disconnect */
194        if (wiimote_disconnect(wiimote)) {
195                wminput_err("error on disconnect");
196                ret = -1;
197        }
198
199        if (conf_unload(&conf)) {
200                ret = -1;
201        }
202
203        return ret;
204}
205
206int wmplugin_set_report_mode(int id, unsigned int flags)
207{
208        conf.plugins[id].rpt_mode_flags = flags;
209
210        if (!init) {
211                wminput_set_report_mode();
212        }
213
214        return 0;
215}
216
217int wminput_set_report_mode()
218{
219        unsigned char rpt_mode_flags;
220        int i;
221
222        rpt_mode_flags = conf.rpt_mode_flags;
223
224        for (i=0; (i < CONF_MAX_PLUGINS) && conf.plugins[i].name; i++) {
225                rpt_mode_flags |= conf.plugins[i].rpt_mode_flags;
226        }
227
228        if (wiimote_command(wiimote, WIIMOTE_CMD_RPT_MODE, rpt_mode_flags)) {
229                wminput_err("error setting report mode");
230                return -1;
231        }
232
233        return 0;
234}
235
236void wiimote_callback(int id, int mesg_count, union wiimote_mesg *mesg[])
237{
238        int i;
239
240        for (i=0; i < mesg_count; i++) {
241                switch (mesg[i]->type) {
242                case WIIMOTE_MESG_BTN:
243                        process_btn_mesg((struct wiimote_btn_mesg *) mesg[i]);
244                        break;
245                case WIIMOTE_MESG_NUNCHUK:
246                        process_nunchuk_mesg((struct wiimote_nunchuk_mesg *) mesg[i]);
247                        break;
248                case WIIMOTE_MESG_CLASSIC:
249                        process_classic_mesg((struct wiimote_classic_mesg *) mesg[i]);
250                        break;
251                default:
252                        break;
253                }
254        }
255        for (i=0; (i < CONF_MAX_PLUGINS) && conf.plugins[i].name; i++) {
256                process_plugin(&conf.plugins[i], mesg_count, mesg);
257        }
258        send_event(&conf, EV_SYN, SYN_REPORT, 0);
259}
260
261void process_btn_mesg(struct wiimote_btn_mesg *mesg)
262{
263        static unsigned short prev_buttons = 0;
264        unsigned short pressed, released;
265        int axis_value;
266        int i;
267
268        /* Wiimote Button/Key Events */
269        pressed = mesg->buttons & ~prev_buttons;
270        released = ~mesg->buttons & prev_buttons;
271        for (i=0; i < CONF_WM_BTN_COUNT; i++) {
272                if (pressed & conf.wiimote_bmap[i].mask) {
273                        send_event(&conf, EV_KEY, conf.wiimote_bmap[i].action, 1);
274                }
275                else if (released & conf.wiimote_bmap[i].mask) {
276                        send_event(&conf, EV_KEY, conf.wiimote_bmap[i].action, 0);
277                }
278        }
279        prev_buttons = mesg->buttons;
280
281        /* Wiimote.Dpad.X */
282        if (conf.amap[CONF_WM_AXIS_DPAD_X].action != -1) {
283                axis_value = 0;
284                if (mesg->buttons & WIIMOTE_BTN_LEFT) {
285                        axis_value = -1;
286                }
287                else if (mesg->buttons & WIIMOTE_BTN_RIGHT) {
288                        axis_value = 1;
289                }
290                if (conf.amap[CONF_WM_AXIS_DPAD_X].flags & CONF_INVERT) {
291                        axis_value *= -1;
292                }
293                send_event(&conf, conf.amap[CONF_WM_AXIS_DPAD_X].axis_type,
294                           conf.amap[CONF_WM_AXIS_DPAD_X].action, axis_value);
295        }
296
297        /* Wiimote.Dpad.Y */
298        if (conf.amap[CONF_WM_AXIS_DPAD_Y].action != -1) {
299                axis_value = 0;
300                if (mesg->buttons & WIIMOTE_BTN_DOWN) {
301                        axis_value = -1;
302                }
303                else if (mesg->buttons & WIIMOTE_BTN_UP) {
304                        axis_value = 1;
305                }
306                if (conf.amap[CONF_WM_AXIS_DPAD_Y].flags & CONF_INVERT) {
307                        axis_value *= -1;
308                }
309                send_event(&conf, conf.amap[CONF_WM_AXIS_DPAD_Y].axis_type,
310                           conf.amap[CONF_WM_AXIS_DPAD_Y].action, axis_value);
311        }
312}
313
314void process_nunchuk_mesg(struct wiimote_nunchuk_mesg *mesg)
315{
316        static unsigned char prev_buttons = 0;
317        unsigned char pressed, released;
318        int axis_value;
319        int i;
320
321        /* Nunchuk Button/Key Events */
322        pressed = mesg->buttons & ~prev_buttons;
323        released = ~mesg->buttons & prev_buttons;
324        for (i=0; i < CONF_NC_BTN_COUNT; i++) {
325                if (pressed & conf.nunchuk_bmap[i].mask) {
326                        send_event(&conf, EV_KEY, conf.nunchuk_bmap[i].action, 1);
327                }
328                else if (released & conf.nunchuk_bmap[i].mask) {
329                        send_event(&conf, EV_KEY, conf.nunchuk_bmap[i].action, 0);
330                }
331        }
332        prev_buttons = mesg->buttons;
333
334        /* Nunchuk.Stick.X */
335        if (conf.amap[CONF_NC_AXIS_STICK_X].action != -1) {
336                axis_value = mesg->stick_x;
337                if (conf.amap[CONF_NC_AXIS_STICK_X].flags & CONF_INVERT) {
338                        axis_value = 0xFF - axis_value;
339                }
340                send_event(&conf, conf.amap[CONF_NC_AXIS_STICK_X].axis_type,
341                           conf.amap[CONF_NC_AXIS_STICK_X].action, axis_value);
342        }
343
344        /* Nunchuk.Stick.Y */
345        if (conf.amap[CONF_NC_AXIS_STICK_Y].action != -1) {
346                axis_value = mesg->stick_y;
347                if (conf.amap[CONF_NC_AXIS_STICK_Y].flags & CONF_INVERT) {
348                        axis_value = 0xFF - axis_value;
349                }
350                send_event(&conf, conf.amap[CONF_NC_AXIS_STICK_Y].axis_type,
351                           conf.amap[CONF_NC_AXIS_STICK_Y].action, axis_value);
352        }
353}
354
355void process_classic_mesg(struct wiimote_classic_mesg *mesg)
356{
357        static unsigned short prev_buttons = 0;
358        unsigned short pressed, released;
359        int axis_value;
360        int i;
361
362        /* Classic Button/Key Events */
363        pressed = mesg->buttons & ~prev_buttons;
364        released = ~mesg->buttons & prev_buttons;
365        for (i=0; i < CONF_CC_BTN_COUNT; i++) {
366                if (pressed & conf.classic_bmap[i].mask) {
367                        send_event(&conf, EV_KEY, conf.classic_bmap[i].action, 1);
368                }
369                else if (released & conf.classic_bmap[i].mask) {
370                        send_event(&conf, EV_KEY, conf.classic_bmap[i].action, 0);
371                }
372        }
373        prev_buttons = mesg->buttons;
374
375        /* Classic.Dpad.X */
376        if (conf.amap[CONF_CC_AXIS_DPAD_X].action != -1) {
377                axis_value = 0;
378                if (mesg->buttons & WIIMOTE_CLASSIC_BTN_LEFT) {
379                        axis_value = -1;
380                }
381                else if (mesg->buttons & WIIMOTE_CLASSIC_BTN_RIGHT) {
382                        axis_value = 1;
383                }
384                if (conf.amap[CONF_CC_AXIS_DPAD_X].flags & CONF_INVERT) {
385                        axis_value *= -1;
386                }
387                send_event(&conf, conf.amap[CONF_CC_AXIS_DPAD_X].axis_type,
388                           conf.amap[CONF_CC_AXIS_DPAD_X].action, axis_value);
389        }
390
391        /* Classic.Dpad.Y */
392        if (conf.amap[CONF_CC_AXIS_DPAD_Y].action != -1) {
393                axis_value = 0;
394                if (mesg->buttons & WIIMOTE_CLASSIC_BTN_DOWN) {
395                        axis_value = -1;
396                }
397                else if (mesg->buttons & WIIMOTE_CLASSIC_BTN_UP) {
398                        axis_value = 1;
399                }
400                if (conf.amap[CONF_CC_AXIS_DPAD_Y].flags & CONF_INVERT) {
401                        axis_value *= -1;
402                }
403                send_event(&conf, conf.amap[CONF_CC_AXIS_DPAD_Y].axis_type,
404                           conf.amap[CONF_CC_AXIS_DPAD_Y].action, axis_value);
405        }
406
407        /* Classic.LStick.X */
408        if (conf.amap[CONF_CC_AXIS_L_STICK_X].action != -1) {
409                axis_value = mesg->l_stick_x;
410                if (conf.amap[CONF_CC_AXIS_L_STICK_X].flags & CONF_INVERT) {
411                        axis_value = WIIMOTE_CLASSIC_L_STICK_MAX - axis_value;
412                }
413                send_event(&conf, conf.amap[CONF_CC_AXIS_L_STICK_X].axis_type,
414                           conf.amap[CONF_CC_AXIS_L_STICK_X].action, axis_value);
415        }
416
417        /* Classic.LStick.Y */
418        if (conf.amap[CONF_CC_AXIS_L_STICK_Y].action != -1) {
419                axis_value = mesg->l_stick_y;
420                if (conf.amap[CONF_CC_AXIS_L_STICK_Y].flags & CONF_INVERT) {
421                        axis_value = WIIMOTE_CLASSIC_L_STICK_MAX - axis_value;
422                }
423                send_event(&conf, conf.amap[CONF_CC_AXIS_L_STICK_Y].axis_type,
424                           conf.amap[CONF_CC_AXIS_L_STICK_Y].action, axis_value);
425        }
426
427        /* Classic.RStick.X */
428        if (conf.amap[CONF_CC_AXIS_R_STICK_X].action != -1) {
429                axis_value = mesg->r_stick_x;
430                if (conf.amap[CONF_CC_AXIS_R_STICK_X].flags & CONF_INVERT) {
431                        axis_value = WIIMOTE_CLASSIC_R_STICK_MAX - axis_value;
432                }
433                send_event(&conf, conf.amap[CONF_CC_AXIS_R_STICK_X].axis_type,
434                           conf.amap[CONF_CC_AXIS_R_STICK_X].action, axis_value);
435        }
436
437        /* Classic.RStick.Y */
438        if (conf.amap[CONF_CC_AXIS_R_STICK_Y].action != -1) {
439                axis_value = mesg->r_stick_y;
440                if (conf.amap[CONF_CC_AXIS_R_STICK_Y].flags & CONF_INVERT) {
441                        axis_value = WIIMOTE_CLASSIC_R_STICK_MAX - axis_value;
442                }
443                send_event(&conf, conf.amap[CONF_CC_AXIS_R_STICK_Y].axis_type,
444                           conf.amap[CONF_CC_AXIS_R_STICK_Y].action, axis_value);
445        }
446
447        /* Classic.LAnalog */
448        if (conf.amap[CONF_CC_AXIS_L].action != -1) {
449                axis_value = mesg->l;
450                if (conf.amap[CONF_CC_AXIS_L].flags & CONF_INVERT) {
451                        axis_value = WIIMOTE_CLASSIC_LR_MAX - axis_value;
452                }
453                send_event(&conf, conf.amap[CONF_CC_AXIS_L].axis_type,
454                           conf.amap[CONF_CC_AXIS_L].action, axis_value);
455        }
456
457        /* Classic.RAnalog */
458        if (conf.amap[CONF_CC_AXIS_R].action != -1) {
459                axis_value = mesg->r;
460                if (conf.amap[CONF_CC_AXIS_R].flags & CONF_INVERT) {
461                        axis_value = WIIMOTE_CLASSIC_LR_MAX - axis_value;
462                }
463                send_event(&conf, conf.amap[CONF_CC_AXIS_R].axis_type,
464                           conf.amap[CONF_CC_AXIS_R].action, axis_value);
465        }
466}
467
468void process_plugin(struct plugin *plugin, int mesg_count,
469                    union wiimote_mesg *mesg[])
470{
471        union wiimote_mesg *plugin_mesg[WIIMOTE_MAX_MESG_COUNT];
472        int plugin_mesg_count = 0;
473        int i;
474        unsigned short flag;
475        struct wmplugin_data *data;
476        unsigned int pressed, released;
477        int axis_value;
478
479        for (i=0; i < mesg_count; i++) {
480                switch (mesg[i]->type) {
481                case WIIMOTE_MESG_STATUS:
482                        flag = WIIMOTE_RPT_STATUS;
483                        break;
484                case WIIMOTE_MESG_BTN:
485                        flag = WIIMOTE_RPT_BTN;
486                        break;
487                case WIIMOTE_MESG_ACC:
488                        flag = WIIMOTE_RPT_ACC;
489                        break;
490                case WIIMOTE_MESG_IR:
491                        flag = WIIMOTE_RPT_IR;
492                        break;
493                case WIIMOTE_MESG_NUNCHUK:
494                        flag = WIIMOTE_RPT_NUNCHUK;
495                        break;
496                case WIIMOTE_MESG_CLASSIC:
497                        flag = WIIMOTE_RPT_CLASSIC;
498                        break;
499                default:
500                        break;
501                }
502                if (plugin->rpt_mode_flags & flag) {
503                        plugin_mesg[plugin_mesg_count++] = mesg[i];
504                }
505        }
506
507        if (plugin_mesg_count > 0) {
508                if (!(data = (*plugin->exec)(plugin_mesg_count, plugin_mesg))) {
509                        return;
510                }
511
512                /* Plugin Button/Key Events */
513                pressed = data->buttons & ~plugin->prev_buttons;
514                released = ~data->buttons & plugin->prev_buttons;
515                for (i=0; i < plugin->info->button_count; i++) {
516                        if (pressed & 1<<i) {
517                                send_event(&conf, EV_KEY, plugin->bmap[i].action, 1);
518                        }
519                        else if (released & 1<<i) {
520                                send_event(&conf, EV_KEY, plugin->bmap[i].action, 0);
521                        }
522                }
523                plugin->prev_buttons = data->buttons;
524
525                /* Plugin Axis Events */
526                for (i=0; i < plugin->info->axis_count; i++) {
527                        if ((plugin->amap[i].action != -1) && data->axes &&
528                          data->axes[i].valid) {
529                                axis_value = data->axes[i].value;
530                                if (plugin->amap[i].flags & CONF_INVERT) {
531                                        axis_value = plugin->info->axis_info[i].max +
532                                                     plugin->info->axis_info[i].min - axis_value;
533                                }
534                                send_event(&conf, plugin->amap[i].axis_type,
535                                           plugin->amap[i].action, axis_value);
536                        }
537                }
538        }
539}
540
Note: See TracBrowser for help on using the browser.