root/wminput/main.c @ 805477a3e8c4bccbd90c78e829870267c783904b

Revision 805477a3e8c4bccbd90c78e829870267c783904b, 14.8 KB (checked in by dsmith <dsmith@…>, 6 years ago)

Merge libcwiid rename into trunk

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