root/wminput/main.c @ a8b4be285821d128706f0edfcd4ac10c7c938a11

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

Changed wiimote_connect to take pointer to bdaddr_t

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