root/wminput/main.c @ 7e5f213decff36c62421b1b3d02d02b3037c79a2

Revision 7e5f213decff36c62421b1b3d02d02b3037c79a2, 19.5 KB (checked in by dsmith <dsmith@…>, 6 years ago)

wminput daemon mode

git-svn-id: http://abstrakraft.org/cwiid/svn/trunk@142 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-08-14 L. Donnie Smith <cwiid@abstrakraft.org>
19 *  * added daemon, quiet, and reconnect options
20 *
21 *  2007-07-29 L. Donnie Smith <cwiid@abstrakraft.org>
22 *  * fixed wait forever logic
23 *
24 *  2007-07-28 L. Donnie Smith <cwiid@abstrakraft.org>
25 *  * added config.h include
26 *  * use PACKAGE_VERSION from config.h instead of CWIID_VERSION
27 *  * added HAVE_PYTHON tests around all python code
28 *
29 *  2007-06-18 L. Donnie Smith <cwiid@abstrakraft.org>
30 *  * revised error messages
31 *
32 *  2007-06-05 L. Donnie Smith <cwiid@abstrakraft.org>
33 *  * refactored to isolate plugin logic
34 *
35 *  2007-06-01 Nick <nickishappy@gmail.com>
36 *  * reworked command-line options (added standard options, long options)
37 *
38 *  2007-06-01 L. Donnie Smith <cwiid@abstrakraft.org>
39 *  * added python plugin support
40 *  * pass mesg instead of &mesg to wmplugin_exec
41 *
42 *  2007-05-16 L. Donnie Smith <cwiid@abstrakraft.org>
43 *  * changed cwiid_{connect,disconnect,command} to
44 *    cwiid_{open,close,request_status|set_led|set_rumble|set_rpt_mode}
45 *
46 *  2007-05-14 L. Donnie Smith <cwiid@abstrakraft.org>
47 *  * added timestamp to message callback
48 *
49 *  2007-04-24 L. Donnie Smith <cwiid@abstrakraft.org>
50 *  * update for API overhaul
51 *
52 *  2007-04-09 L. Donnie Smith <cwiid@abstrakraft.org>
53 *  * updated for libcwiid rename
54 *
55 *  2007-04-04 L. Donnie Smith <cwiid@abstrakraft.org>
56 *  * exit on cwiid_error
57 *
58 *  2007-03-03 L. Donnie Smith <cwiid@abstrakraft.org>
59 *  * Initial ChangeLog
60 *  * type audit (stdint, const, char booleans)
61 */
62
63#ifdef HAVE_CONFIG_H
64#include "config.h"
65#endif
66
67#include <stdint.h>
68#include <stdio.h>
69#include <stdlib.h>
70#include <getopt.h>
71
72#include <pthread.h>
73#include <signal.h>
74#include <sys/types.h>
75#include <unistd.h>
76
77#include <cwiid.h>
78
79#include "conf.h"
80#include "util.h"
81#include "wmplugin.h"
82#include "c_plugin.h"
83
84#ifdef HAVE_PYTHON
85#include "py_plugin.h"
86#endif
87
88struct conf conf;
89
90/* Prototypes */
91cwiid_mesg_callback_t cwiid_callback;
92int wminput_set_report_mode();
93void process_btn_mesg(struct cwiid_btn_mesg *mesg);
94void process_nunchuk_mesg(struct cwiid_nunchuk_mesg *mesg);
95void process_classic_mesg(struct cwiid_classic_mesg *mesg);
96void process_plugin(struct plugin *, int, union cwiid_mesg []);
97
98/* Globals */
99cwiid_wiimote_t *wiimote;
100char init;
101
102#define DEFAULT_CONFIG_FILE     "default"
103
104#define HOME_DIR_LEN    128
105
106void print_usage(void)
107{
108        printf("wminput is a program that allows you to use a wiimote as a standard input device\n");
109        printf("Usage: %s [OPTIONS]...\n\n", "wminput");
110        printf("Options:\n");
111        printf("\t-h, --help\t\tPrints this output.\n");
112        printf("\t-v, --version\t\toutput version information and exit.\n");
113        printf("\t-c, --config [file]\tChoose config file to use.\n");
114        printf("\t-d, --daemon\t\tImplies -q, -r, and -w.\n");
115        printf("\t-q, --quiet\t\tReduce output to errors\n");
116        printf("\t-r, --reconnect [wait]\t\tAutomatically try reconnect after wiimote disconnect.\n");
117        printf("\t-w, --wait\t\tWait indefinitely for wiimote to connect.\n");
118}
119
120int main(int argc, char *argv[])
121{
122        char wait_forever = 0, quiet = 0, reconnect = 0, reconnect_wait = 0;
123        char *config_search_dirs[3], *plugin_search_dirs[3];
124        char *config_filename = DEFAULT_CONFIG_FILE;
125        char home_config_dir[HOME_DIR_LEN];
126        char home_plugin_dir[HOME_DIR_LEN];
127        char *tmp;
128        int c, i;
129        char *str_addr;
130        bdaddr_t bdaddr, current_bdaddr;
131        sigset_t sigset;
132        int signum, ret=0;
133        struct uinput_listen_data uinput_listen_data;
134        pthread_t uinput_listen_thread;
135
136        init = 1;
137
138        /* Parse Options */
139        while (1) {
140                int option_index = 0;
141
142                static struct option long_options[] = {
143                        {"help", 0, 0, 'h'},
144                        {"version", 0, 0, 'v'},
145                        {"config", 1, 0, 'c'},
146                        {"daemon", 0, 0, 'd'},
147                        {"quiet", 0, 0, 'q'},
148                        {"reconnect", 2, 0, 'r'},
149                        {"wait", 0, 0, 'w'},
150                        {0, 0, 0, 0}
151                };
152
153                c = getopt_long (argc, argv, "hvc:dqr::w", long_options, &option_index);
154
155                if (c == -1) {
156                        break;
157                }
158
159                switch (c) {
160                case 'h':
161                        print_usage();
162                        return 0;
163                        break;
164                case 'v':
165                        printf("CWiid Version %s\n", PACKAGE_VERSION);
166                        return 0;
167                        break;
168                case 'c':
169                        config_filename = optarg;
170                        break;
171                case 'd':
172                        wait_forever = 1;
173                        quiet = 1;
174                        reconnect = 1;
175                        break;
176                case 'q':
177                        quiet = 1;
178                        break;
179                case 'r':
180                        reconnect = 1;
181                        if (optarg) {
182                                reconnect_wait = strtol(optarg, &tmp, 10);
183                                if (*tmp != '\0') {
184                                        wminput_err("bad reconnect wait time");
185                                        return -1;
186                                }
187                        }
188                        break;
189                case 'w':
190                        wait_forever = 1;
191                        break;
192                case '?':
193                        printf("Try `wminput --help` for more information\n");
194                        return 1;
195                        break;
196                default:
197                        return -1;
198                        break;
199                }
200        }
201
202        if (c_init()) {
203                return -1;
204        }
205
206#ifdef HAVE_PYTHON
207        if (py_init()) {
208                return -1;
209        }
210#endif
211
212        /* Load Config */
213        /* Setup search directory arrays */
214        if ((tmp = getenv("HOME")) == NULL) {
215                wminput_err("Unable to find home directory");
216                config_search_dirs[0] = WMINPUT_CONFIG_DIR;
217                plugin_search_dirs[0] = CWIID_PLUGINS_DIR;
218                config_search_dirs[1] = plugin_search_dirs[1] = NULL;
219        }
220        else {
221                snprintf(home_config_dir, HOME_DIR_LEN, "%s/.cwiid/wminput", tmp);
222                snprintf(home_plugin_dir, HOME_DIR_LEN, "%s/.cwiid/plugins", tmp);
223                config_search_dirs[0] = home_config_dir;
224                plugin_search_dirs[0] = home_plugin_dir;
225                config_search_dirs[1] = WMINPUT_CONFIG_DIR;
226                plugin_search_dirs[1] = CWIID_PLUGINS_DIR;
227                config_search_dirs[2] = plugin_search_dirs[2] = NULL;
228        }
229
230        if (conf_load(&conf, config_filename, config_search_dirs,
231          plugin_search_dirs)) {
232                return -1;
233        }
234
235        /* Determine BDADDR */
236        /* priority: command-line option, environment variable, BDADDR_ANY */
237        if (optind < argc) {
238                if (str2ba(argv[optind], &bdaddr)) {
239                        wminput_err("invalid bdaddr");
240                        bdaddr = *BDADDR_ANY;
241                }
242                optind++;
243                if (optind < argc) {
244                        wminput_err("invalid command-line");
245                        print_usage();
246                        conf_unload(&conf);
247                        return -1;
248                }
249        }
250        else if ((str_addr = getenv(WIIMOTE_BDADDR)) != NULL) {
251                if (str2ba(str_addr, &bdaddr)) {
252                        wminput_err("invalid address in %s", WIIMOTE_BDADDR);
253                        bdaddr = *BDADDR_ANY;
254                }
255        }
256        else {
257                bdaddr = *BDADDR_ANY;
258        }
259
260        sigemptyset(&sigset);
261        sigaddset(&sigset, SIGTERM);
262        sigaddset(&sigset, SIGINT);
263        sigaddset(&sigset, SIGUSR1);
264
265        do {
266                bacpy(&current_bdaddr, &bdaddr);
267
268                /* Wiimote Connect */
269                if (!quiet) {
270                        printf("Put Wiimote in discoverable mode now (press 1+2)...\n");
271                }
272                if (wait_forever) {
273                        if (!bacmp(&current_bdaddr, BDADDR_ANY)) {
274                                if (cwiid_find_wiimote(&current_bdaddr, -1)) {
275                                        wminput_err("error finding wiimote");
276                                        conf_unload(&conf);
277                                        return -1;
278                                }
279                        }
280                        /* TODO: avoid continuously calling cwiid_open */
281                        /* TODO: kill error messages on failed cwiid_open calls */
282                        while (!(wiimote = cwiid_open(&current_bdaddr, CWIID_FLAG_MESG_IFC)));
283                }
284                else {
285                        if ((wiimote = cwiid_open(&current_bdaddr, CWIID_FLAG_MESG_IFC)) == NULL) {
286                                wminput_err("unable to connect");
287                                conf_unload(&conf);
288                                return -1;
289                        }
290                }
291                if (cwiid_set_mesg_callback(wiimote, &cwiid_callback)) {
292                        wminput_err("error setting callback");
293                        conf_unload(&conf);
294                        return -1;
295                }
296
297                if (c_wiimote(wiimote)) {
298                        conf_unload(&conf);
299                        return -1;
300                }
301#ifdef HAVE_PYTHON
302                if (py_wiimote(wiimote)) {
303                        conf_unload(&conf);
304                        return -1;
305                }
306#endif
307
308                /* init plugins */
309                for (i=0; (i < CONF_MAX_PLUGINS) && conf.plugins[i].name; i++) {
310                        switch (conf.plugins[i].type) {
311                        case PLUGIN_C:
312                                if (c_plugin_init(&conf.plugins[i], i)) {
313                                        wminput_err("error on %s init", conf.plugins[i].name);
314                                        conf_unload(&conf);
315                                        cwiid_close(wiimote);
316                                        return -1;
317                                }
318                                break;
319#ifdef HAVE_PYTHON
320                        case PLUGIN_PYTHON:
321                                if (py_plugin_init(&conf.plugins[i], i)) {
322                                        wminput_err("error %s init", conf.plugins[i].name);
323                                        conf_unload(&conf);
324                                        cwiid_close(wiimote);
325                                        return -1;
326                                }
327                                break;
328#endif
329                        }
330                }
331
332                if (wminput_set_report_mode()) {
333                        conf_unload(&conf);
334                        cwiid_close(wiimote);
335                        return -1;
336                }
337
338                uinput_listen_data.wiimote = wiimote;
339                uinput_listen_data.conf = &conf;
340                if (pthread_create(&uinput_listen_thread, NULL,
341                                   (void *(*)(void *))uinput_listen,
342                                   &uinput_listen_data)) {
343                        wminput_err("error starting uinput listen thread");
344                        conf_unload(&conf);
345                        cwiid_close(wiimote);
346                        return -1;
347                }
348
349                if (!quiet) {
350                        printf("Ready.\n");
351                }
352
353                init = 0;
354
355                /* wait */
356                sigprocmask(SIG_BLOCK, &sigset, NULL);
357                sigwait(&sigset, &signum);
358                sigprocmask(SIG_UNBLOCK, &sigset, NULL);
359
360                if ((signum == SIGTERM) || (signum == SIGINT)) {
361                        reconnect = 0;
362                }
363
364                if (pthread_cancel(uinput_listen_thread)) {
365                        wminput_err("Error canceling uinput listen thread");
366                        ret = -1;
367                }
368                else if (pthread_join(uinput_listen_thread, NULL)) {
369                        wminput_err("Error joining uinput listen thread");
370                        ret = -1;
371                }
372
373                c_wiimote_deinit();
374#ifdef HAVE_PYTHON
375                py_wiimote_deinit();
376#endif
377
378                /* disconnect */
379                if (cwiid_close(wiimote)) {
380                        wminput_err("Error on wiimote disconnect");
381                        ret = -1;
382                }
383
384                if (reconnect && reconnect_wait) {
385                        sleep(reconnect_wait);
386                }
387        } while (reconnect);
388
389        if (conf_unload(&conf)) {
390                ret = -1;
391        }
392
393        c_deinit();
394#ifdef HAVE_PYTHON
395        py_deinit();
396#endif
397
398        if (!quiet) {
399                printf("Exiting.\n");
400        }
401
402        return ret;
403}
404
405int wminput_set_report_mode()
406{
407        unsigned char rpt_mode_flags;
408        int i;
409
410        rpt_mode_flags = conf.rpt_mode_flags;
411
412        for (i=0; (i < CONF_MAX_PLUGINS) && conf.plugins[i].name; i++) {
413                rpt_mode_flags |= conf.plugins[i].rpt_mode_flags;
414        }
415
416        if (cwiid_set_rpt_mode(wiimote, rpt_mode_flags)) {
417                wminput_err("Error setting report mode");
418                return -1;
419        }
420
421        return 0;
422}
423
424int wmplugin_set_rpt_mode(int id, uint8_t flags)
425{
426        conf.plugins[id].rpt_mode_flags = flags;
427
428        if (!init) {
429                wminput_set_report_mode();
430        }
431
432        return 0;
433}
434
435void cwiid_callback(cwiid_wiimote_t *wiimote, int mesg_count,
436                    union cwiid_mesg mesg[], struct timespec *timestamp)
437{
438        int i;
439
440        for (i=0; i < mesg_count; i++) {
441                switch (mesg[i].type) {
442                case CWIID_MESG_BTN:
443                        process_btn_mesg((struct cwiid_btn_mesg *) &mesg[i]);
444                        break;
445                case CWIID_MESG_NUNCHUK:
446                        process_nunchuk_mesg((struct cwiid_nunchuk_mesg *) &mesg[i]);
447                        break;
448                case CWIID_MESG_CLASSIC:
449                        process_classic_mesg((struct cwiid_classic_mesg *) &mesg[i]);
450                        break;
451                case CWIID_MESG_ERROR:
452                        if (kill(getpid(),SIGUSR1)) {
453                                wminput_err("Error sending SIGUSR1");
454                        }
455                        break;
456                default:
457                        break;
458                }
459        }
460        for (i=0; (i < CONF_MAX_PLUGINS) && conf.plugins[i].name; i++) {
461                process_plugin(&conf.plugins[i], mesg_count, mesg);
462        }
463        send_event(&conf, EV_SYN, SYN_REPORT, 0);
464}
465
466void process_btn_mesg(struct cwiid_btn_mesg *mesg)
467{
468        static uint16_t prev_buttons = 0;
469        uint16_t pressed, released;
470        __s32 axis_value;
471        int i;
472
473        /* Wiimote Button/Key Events */
474        pressed = mesg->buttons & ~prev_buttons;
475        released = ~mesg->buttons & prev_buttons;
476        for (i=0; i < CONF_WM_BTN_COUNT; i++) {
477                if (conf.wiimote_bmap[i].active) {
478                        if (pressed & conf.wiimote_bmap[i].mask) {
479                                send_event(&conf, EV_KEY, conf.wiimote_bmap[i].action, 1);
480                        }
481                        else if (released & conf.wiimote_bmap[i].mask) {
482                                send_event(&conf, EV_KEY, conf.wiimote_bmap[i].action, 0);
483                        }
484                }
485        }
486        prev_buttons = mesg->buttons;
487
488        /* Wiimote.Dpad.X */
489        if (conf.amap[CONF_WM_AXIS_DPAD_X].active) {
490                axis_value = 0;
491                if (mesg->buttons & CWIID_BTN_LEFT) {
492                        axis_value = -1;
493                }
494                else if (mesg->buttons & CWIID_BTN_RIGHT) {
495                        axis_value = 1;
496                }
497                if (conf.amap[CONF_WM_AXIS_DPAD_X].flags & CONF_INVERT) {
498                        axis_value *= -1;
499                }
500                send_event(&conf, conf.amap[CONF_WM_AXIS_DPAD_X].axis_type,
501                           conf.amap[CONF_WM_AXIS_DPAD_X].action, axis_value);
502        }
503
504        /* Wiimote.Dpad.Y */
505        if (conf.amap[CONF_WM_AXIS_DPAD_Y].active) {
506                axis_value = 0;
507                if (mesg->buttons & CWIID_BTN_DOWN) {
508                        axis_value = -1;
509                }
510                else if (mesg->buttons & CWIID_BTN_UP) {
511                        axis_value = 1;
512                }
513                if (conf.amap[CONF_WM_AXIS_DPAD_Y].flags & CONF_INVERT) {
514                        axis_value *= -1;
515                }
516                send_event(&conf, conf.amap[CONF_WM_AXIS_DPAD_Y].axis_type,
517                           conf.amap[CONF_WM_AXIS_DPAD_Y].action, axis_value);
518        }
519}
520
521void process_nunchuk_mesg(struct cwiid_nunchuk_mesg *mesg)
522{
523        static uint8_t prev_buttons = 0;
524        uint8_t pressed, released;
525        __s32 axis_value;
526        int i;
527
528        /* Nunchuk Button/Key Events */
529        pressed = mesg->buttons & ~prev_buttons;
530        released = ~mesg->buttons & prev_buttons;
531        for (i=0; i < CONF_NC_BTN_COUNT; i++) {
532                if (conf.nunchuk_bmap[i].active) {
533                        if (pressed & conf.nunchuk_bmap[i].mask) {
534                                send_event(&conf, EV_KEY, conf.nunchuk_bmap[i].action, 1);
535                        }
536                        else if (released & conf.nunchuk_bmap[i].mask) {
537                                send_event(&conf, EV_KEY, conf.nunchuk_bmap[i].action, 0);
538                        }
539                }
540        }
541        prev_buttons = mesg->buttons;
542
543        /* Nunchuk.Stick.X */
544        if (conf.amap[CONF_NC_AXIS_STICK_X].active) {
545                axis_value = mesg->stick[CWIID_X];
546                if (conf.amap[CONF_NC_AXIS_STICK_X].flags & CONF_INVERT) {
547                        axis_value = 0xFF - axis_value;
548                }
549                send_event(&conf, conf.amap[CONF_NC_AXIS_STICK_X].axis_type,
550                           conf.amap[CONF_NC_AXIS_STICK_X].action, axis_value);
551        }
552
553        /* Nunchuk.Stick.Y */
554        if (conf.amap[CONF_NC_AXIS_STICK_Y].active) {
555                axis_value = mesg->stick[CWIID_Y];
556                if (conf.amap[CONF_NC_AXIS_STICK_Y].flags & CONF_INVERT) {
557                        axis_value = 0xFF - axis_value;
558                }
559                send_event(&conf, conf.amap[CONF_NC_AXIS_STICK_Y].axis_type,
560                           conf.amap[CONF_NC_AXIS_STICK_Y].action, axis_value);
561        }
562}
563
564void process_classic_mesg(struct cwiid_classic_mesg *mesg)
565{
566        static uint16_t prev_buttons = 0;
567        uint16_t pressed, released;
568        __s32 axis_value;
569        int i;
570
571        /* Classic Button/Key Events */
572        pressed = mesg->buttons & ~prev_buttons;
573        released = ~mesg->buttons & prev_buttons;
574        for (i=0; i < CONF_CC_BTN_COUNT; i++) {
575                if (conf.classic_bmap[i].active) {
576                        if (pressed & conf.classic_bmap[i].mask) {
577                                send_event(&conf, EV_KEY, conf.classic_bmap[i].action, 1);
578                        }
579                        else if (released & conf.classic_bmap[i].mask) {
580                                send_event(&conf, EV_KEY, conf.classic_bmap[i].action, 0);
581                        }
582                }
583        }
584        prev_buttons = mesg->buttons;
585
586        /* Classic.Dpad.X */
587        if (conf.amap[CONF_CC_AXIS_DPAD_X].active) {
588                axis_value = 0;
589                if (mesg->buttons & CWIID_CLASSIC_BTN_LEFT) {
590                        axis_value = -1;
591                }
592                else if (mesg->buttons & CWIID_CLASSIC_BTN_RIGHT) {
593                        axis_value = 1;
594                }
595                if (conf.amap[CONF_CC_AXIS_DPAD_X].flags & CONF_INVERT) {
596                        axis_value *= -1;
597                }
598                send_event(&conf, conf.amap[CONF_CC_AXIS_DPAD_X].axis_type,
599                           conf.amap[CONF_CC_AXIS_DPAD_X].action, axis_value);
600        }
601
602        /* Classic.Dpad.Y */
603        if (conf.amap[CONF_CC_AXIS_DPAD_Y].active) {
604                axis_value = 0;
605                if (mesg->buttons & CWIID_CLASSIC_BTN_DOWN) {
606                        axis_value = -1;
607                }
608                else if (mesg->buttons & CWIID_CLASSIC_BTN_UP) {
609                        axis_value = 1;
610                }
611                if (conf.amap[CONF_CC_AXIS_DPAD_Y].flags & CONF_INVERT) {
612                        axis_value *= -1;
613                }
614                send_event(&conf, conf.amap[CONF_CC_AXIS_DPAD_Y].axis_type,
615                           conf.amap[CONF_CC_AXIS_DPAD_Y].action, axis_value);
616        }
617
618        /* Classic.LStick.X */
619        if (conf.amap[CONF_CC_AXIS_L_STICK_X].active) {
620                axis_value = mesg->l_stick[CWIID_X];
621                if (conf.amap[CONF_CC_AXIS_L_STICK_X].flags & CONF_INVERT) {
622                        axis_value = CWIID_CLASSIC_L_STICK_MAX - axis_value;
623                }
624                send_event(&conf, conf.amap[CONF_CC_AXIS_L_STICK_X].axis_type,
625                           conf.amap[CONF_CC_AXIS_L_STICK_X].action, axis_value);
626        }
627
628        /* Classic.LStick.Y */
629        if (conf.amap[CONF_CC_AXIS_L_STICK_Y].active) {
630                axis_value = mesg->l_stick[CWIID_Y];
631                if (conf.amap[CONF_CC_AXIS_L_STICK_Y].flags & CONF_INVERT) {
632                        axis_value = CWIID_CLASSIC_L_STICK_MAX - axis_value;
633                }
634                send_event(&conf, conf.amap[CONF_CC_AXIS_L_STICK_Y].axis_type,
635                           conf.amap[CONF_CC_AXIS_L_STICK_Y].action, axis_value);
636        }
637
638        /* Classic.RStick.X */
639        if (conf.amap[CONF_CC_AXIS_R_STICK_X].active) {
640                axis_value = mesg->r_stick[CWIID_X];
641                if (conf.amap[CONF_CC_AXIS_R_STICK_X].flags & CONF_INVERT) {
642                        axis_value = CWIID_CLASSIC_R_STICK_MAX - axis_value;
643                }
644                send_event(&conf, conf.amap[CONF_CC_AXIS_R_STICK_X].axis_type,
645                           conf.amap[CONF_CC_AXIS_R_STICK_X].action, axis_value);
646        }
647
648        /* Classic.RStick.Y */
649        if (conf.amap[CONF_CC_AXIS_R_STICK_Y].active) {
650                axis_value = mesg->r_stick[CWIID_Y];
651                if (conf.amap[CONF_CC_AXIS_R_STICK_Y].flags & CONF_INVERT) {
652                        axis_value = CWIID_CLASSIC_R_STICK_MAX - axis_value;
653                }
654                send_event(&conf, conf.amap[CONF_CC_AXIS_R_STICK_Y].axis_type,
655                           conf.amap[CONF_CC_AXIS_R_STICK_Y].action, axis_value);
656        }
657
658        /* Classic.LAnalog */
659        if (conf.amap[CONF_CC_AXIS_L].active) {
660                axis_value = mesg->l;
661                if (conf.amap[CONF_CC_AXIS_L].flags & CONF_INVERT) {
662                        axis_value = CWIID_CLASSIC_LR_MAX - axis_value;
663                }
664                send_event(&conf, conf.amap[CONF_CC_AXIS_L].axis_type,
665                           conf.amap[CONF_CC_AXIS_L].action, axis_value);
666        }
667
668        /* Classic.RAnalog */
669        if (conf.amap[CONF_CC_AXIS_R].active) {
670                axis_value = mesg->r;
671                if (conf.amap[CONF_CC_AXIS_R].flags & CONF_INVERT) {
672                        axis_value = CWIID_CLASSIC_LR_MAX - axis_value;
673                }
674                send_event(&conf, conf.amap[CONF_CC_AXIS_R].axis_type,
675                           conf.amap[CONF_CC_AXIS_R].action, axis_value);
676        }
677}
678
679void process_plugin(struct plugin *plugin, int mesg_count,
680                    union cwiid_mesg mesg[])
681{
682        static union cwiid_mesg plugin_mesg[CWIID_MAX_MESG_COUNT];
683        int plugin_mesg_count = 0;
684        int i;
685        uint8_t flag;
686        uint16_t pressed, released;
687        __s32 axis_value;
688
689        for (i=0; i < mesg_count; i++) {
690                switch (mesg[i].type) {
691                case CWIID_MESG_STATUS:
692                        flag = CWIID_RPT_STATUS;
693                        break;
694                case CWIID_MESG_BTN:
695                        flag = CWIID_RPT_BTN;
696                        break;
697                case CWIID_MESG_ACC:
698                        flag = CWIID_RPT_ACC;
699                        break;
700                case CWIID_MESG_IR:
701                        flag = CWIID_RPT_IR;
702                        break;
703                case CWIID_MESG_NUNCHUK:
704                        flag = CWIID_RPT_NUNCHUK;
705                        break;
706                case CWIID_MESG_CLASSIC:
707                        flag = CWIID_RPT_CLASSIC;
708                        break;
709                default:
710                        break;
711                }
712                if (plugin->rpt_mode_flags & flag) {
713                        /* TODO: copy correct (smaller) message size */
714                        memcpy(&plugin_mesg[plugin_mesg_count++], &mesg[i], sizeof mesg[i]);
715                }
716        }
717
718        if (plugin_mesg_count > 0) {
719                switch (plugin->type) {
720                case PLUGIN_C:
721                        if (c_plugin_exec(plugin, plugin_mesg_count, plugin_mesg)) {
722                                return;
723                        }
724                        break;
725#ifdef HAVE_PYTHON
726                case PLUGIN_PYTHON:
727                        if (py_plugin_exec(plugin, plugin_mesg_count, plugin_mesg)) {
728                                return;
729                        }
730                        break;
731#endif
732                }
733
734                /* Plugin Button/Key Events */
735                pressed = plugin->data->buttons & ~plugin->prev_buttons;
736                released = ~plugin->data->buttons & plugin->prev_buttons;
737                for (i=0; i < plugin->info->button_count; i++) {
738                        if (plugin->bmap[i].active) {
739                                if (pressed & 1<<i) {
740                                        send_event(&conf, EV_KEY, plugin->bmap[i].action, 1);
741                                }
742                                else if (released & 1<<i) {
743                                        send_event(&conf, EV_KEY, plugin->bmap[i].action, 0);
744                                }
745                        }
746                }
747                plugin->prev_buttons = plugin->data->buttons;
748
749                /* Plugin Axis Events */
750                for (i=0; i < plugin->info->axis_count; i++) {
751                        if (plugin->amap[i].active && plugin->data->axes &&
752                          plugin->data->axes[i].valid) {
753                                axis_value = plugin->data->axes[i].value;
754                                if (plugin->amap[i].flags & CONF_INVERT) {
755                                        axis_value = plugin->info->axis_info[i].max +
756                                                     plugin->info->axis_info[i].min - axis_value;
757                                }
758                                send_event(&conf, plugin->amap[i].axis_type,
759                                           plugin->amap[i].action, axis_value);
760                        }
761                }
762        }
763}
Note: See TracBrowser for help on using the browser.