root/branches/dev/wminput/conf.c

Revision 124, 15.1 kB (checked in by dsmith, 2 years ago)

wminput plugin refactoring

Line 
1 /* Copyright (C) 2007 L. Donnie Smith <cwiid@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-06-05 L. Donnie Smith <cwiid@abstrakraft.org>
19  *  * refactored to isolate plugin logic
20  *
21  *  2007-06-03 L. Donnie Smith <cwiid@abstrakraft.org>
22  *  * fixed plugin->data malloc bug
23  *
24  *  2007-06-01 L. Donnie Smith <cwiid@abstrakraft.org>
25  *  * added python plugin support
26  *  * changed param interface (pass pointers)
27  *
28  *  2007-04-15 <work.eric@gmail.com>
29  *  * fixed classic controller configuration bug
30  *
31  *  2007-04-08 L. Donnie Smith <cwiid@abstrakraft.org>
32  *  * fixed pointer qualifier warning in get_plugin
33  *  * created conf_plugin_param_{int,float} functions
34  *
35  *  2007-03-03 L. Donnie Smith <cwiid@abstrakraft.org>
36  *  * Initial ChangeLog
37  *  * type audit (stdint, const, char booleans)
38  */
39
40 #include <stdint.h>
41 #include <stdio.h>
42 #include <stdlib.h>
43 #include <string.h>
44
45 #include "conf.h"
46 #include "util.h"
47 #include "y.tab.h"
48 #include "c_plugin.h"
49 #include "py_plugin.h"
50
51 extern FILE *yyin;
52 extern int yyparse();
53
54 extern struct lookup_enum action_enum[];
55 struct conf *cur_conf;
56
57 struct plugin *get_plugin(struct conf *conf, const char *name);
58
59 int conf_load(struct conf *conf, const char *conf_name,
60               char *config_search_dirs[], char *plugin_search_dirs[])
61 {
62         conf_init(conf);
63         cur_conf = conf;
64
65         cur_conf->config_search_dirs = config_search_dirs;
66         cur_conf->plugin_search_dirs = plugin_search_dirs;
67         if (!(yyin = conf_push_config(cur_conf, conf_name, NULL))) {
68                 return -1;
69         }
70
71         if (yyparse()) {
72                 if (fclose(yyin)) {
73                         wminput_err("error closing configuration file");
74                 }
75                 conf_unload(cur_conf);
76                 return -1;
77         }
78
79         if (uinput_open(cur_conf)) {
80                 conf_unload(cur_conf);
81                 return -1;
82         }
83
84         return 0;
85 }
86
87 int conf_unload(struct conf *conf)
88 {
89         int i;
90
91         for (i=0; i < CONF_MAX_PLUGINS; i++) {
92                 if (conf->plugins[i].name) {
93                         free(conf->plugins[i].name);
94                         switch (conf->plugins[i].type) {
95                         case PLUGIN_C:
96                                 c_plugin_close(&conf->plugins[i]);
97                                 break;
98                         case PLUGIN_PYTHON:
99                                 py_plugin_close(&conf->plugins[i]);
100                                 break;
101                         }
102                 }
103         }
104
105         return 0;
106 }
107
108 int conf_ff(struct conf *conf, unsigned char enabled)
109 {
110         if (enabled) {
111                 conf->ff = 1;
112                 conf->dev.ff_effects_max = 1;
113         }
114         else {
115                 conf->ff = 0;
116                 conf->dev.ff_effects_max = 0;
117         }
118
119         return 0;
120 }
121
122 int conf_button(struct conf *conf, int source, __u16 button, __u16 action)
123 {
124         switch (source) {
125         case CONF_WM:
126                 conf->rpt_mode_flags |= CWIID_RPT_BTN;
127                 conf->wiimote_bmap[button].active = 1;
128                 conf->wiimote_bmap[button].action = action;
129                 break;
130         case CONF_NC:
131                 conf->rpt_mode_flags |= CWIID_RPT_NUNCHUK;
132                 conf->nunchuk_bmap[button].active = 1;
133                 conf->nunchuk_bmap[button].action = action;
134                 break;
135         case CONF_CC:
136                 conf->rpt_mode_flags |= CWIID_RPT_CLASSIC;
137                 conf->classic_bmap[button].active = 1;
138                 conf->classic_bmap[button].action = action;
139                 break;
140         }
141
142         return 0;
143 }
144
145 int conf_axis(struct conf *conf, int axis, __u16 axis_type, __u16 action,
146               char flags)
147 {
148         conf->amap[axis].active = 1;
149         conf->amap[axis].axis_type = axis_type;
150         conf->amap[axis].action = action;
151         conf->amap[axis].flags = flags;
152
153         if (axis_type == EV_ABS) {
154                 if (!(conf->dev.absmax[action] == -1) ||
155                   !(conf->dev.absmin[action] == -1)) {
156                         wminput_err("Warning: duplicate absolute axis assignment");
157                 }
158         }
159
160         switch (axis) {
161         case CONF_WM_AXIS_DPAD_X:
162         case CONF_WM_AXIS_DPAD_Y:
163                 conf->rpt_mode_flags |= CWIID_RPT_BTN;
164                 if (axis_type == EV_ABS) {
165                         conf->dev.absmax[action] = 1;
166                         conf->dev.absmin[action] = -1;
167                         conf->dev.absfuzz[action] = 0;
168                         conf->dev.absflat[action] = 0;
169                 }
170                 break;
171         case CONF_NC_AXIS_STICK_X:
172         case CONF_NC_AXIS_STICK_Y:
173                 conf->rpt_mode_flags |= CWIID_RPT_NUNCHUK;
174                 if (axis_type == EV_ABS) {
175                         conf->dev.absmax[action] = 0xFF;
176                         conf->dev.absmin[action] = 0;
177                         conf->dev.absfuzz[action] = 0;
178                         conf->dev.absflat[action] = 0;
179                 }
180                 break;
181         case CONF_CC_AXIS_DPAD_X:
182         case CONF_CC_AXIS_DPAD_Y:
183                 conf->rpt_mode_flags |= CWIID_RPT_CLASSIC;
184                 if (axis_type == EV_ABS) {
185                         conf->dev.absmax[action] = 1;
186                         conf->dev.absmin[action] = -1;
187                         conf->dev.absfuzz[action] = 0;
188                         conf->dev.absflat[action] = 0;
189                 }
190                 break;
191         case CONF_CC_AXIS_L_STICK_X:
192         case CONF_CC_AXIS_L_STICK_Y:
193                 conf->rpt_mode_flags |= CWIID_RPT_CLASSIC;
194                 if (axis_type == EV_ABS) {
195                         conf->dev.absmax[action] = CWIID_CLASSIC_L_STICK_MAX;
196                         conf->dev.absmin[action] = 0;
197                         conf->dev.absfuzz[action] = 0;
198                         conf->dev.absflat[action] = 0;
199                 }
200                 break;
201         case CONF_CC_AXIS_R_STICK_X:
202         case CONF_CC_AXIS_R_STICK_Y:
203                 conf->rpt_mode_flags |= CWIID_RPT_CLASSIC;
204                 if (axis_type == EV_ABS) {
205                         conf->dev.absmax[action] = CWIID_CLASSIC_R_STICK_MAX;
206                         conf->dev.absmin[action] = 0;
207                         conf->dev.absfuzz[action] = 0;
208                         conf->dev.absflat[action] = 0;
209                 }
210                 break;
211         case CONF_CC_AXIS_L:
212         case CONF_CC_AXIS_R:
213                 conf->rpt_mode_flags |= CWIID_RPT_CLASSIC;
214                 if (axis_type == EV_ABS) {
215                         conf->dev.absmax[action] = CWIID_CLASSIC_LR_MAX;
216                         conf->dev.absmin[action] = 0;
217                         conf->dev.absfuzz[action] = 0;
218                         conf->dev.absflat[action] = 0;
219                 }
220                 break;
221         }
222
223         return 0;
224 }
225
226 int conf_plugin_button(struct conf *conf, const char *name, const char *button,
227                        __u16 action)
228 {
229         struct plugin *plugin;
230         int i;
231         unsigned char button_found = 0;
232
233         if ((plugin = get_plugin(conf, name)) == NULL) {
234                 return -1;
235         }
236
237         for (i=0; i < plugin->info->button_count; i++) {
238                 if (!strcmp(plugin->info->button_info[i].name, button)) {
239                         button_found = 1;
240                         break;
241                 }
242         }
243
244         if (!button_found) {
245                 wminput_err("Invalid plugin button: %s.%s", name, button);
246                 return -1;
247         }
248         else {
249                 plugin->bmap[i].active = 1;
250                 plugin->bmap[i].action = action;
251         }
252
253         return 0;
254 }
255
256 int conf_plugin_axis(struct conf *conf, const char *name, const char *axis,
257                      __u16 axis_type, __u16 action, char flags)
258 {
259         struct plugin *plugin;
260         int i;
261         unsigned char axis_found = 0;
262         unsigned char mismatch = 0;
263
264         if ((plugin = get_plugin(conf, name)) == NULL) {
265                 return -1;
266         }
267
268         for (i=0; i < plugin->info->axis_count; i++) {
269                 if (!strcmp(plugin->info->axis_info[i].name, axis)) {
270                         axis_found = 1;
271                         break;
272                 }
273         }
274
275         if (!axis_found) {
276                 wminput_err("Invalid plugin axis: %s.%s", name, axis);
277                 return -1;
278         }
279
280         switch (axis_type) {
281         case CONF_ABS:
282                 if (!(plugin->info->axis_info[i].type & WMPLUGIN_ABS)) {
283                         mismatch = 1;
284                 }
285                 break;
286         case CONF_REL:
287                 if (!(plugin->info->axis_info[i].type & WMPLUGIN_REL)) {
288                         mismatch = 1;
289                 }
290                 break;
291         }
292         if (mismatch) {
293                 wminput_err("Warning: axis type mismatch - %s.%s", name, axis);
294         }
295
296         plugin->amap[i].active = 1;
297         plugin->amap[i].axis_type = axis_type;
298         plugin->amap[i].action = action;
299         plugin->amap[i].flags = flags;
300
301         if (axis_type == EV_ABS) {
302                 if (!(conf->dev.absmax[action] == -1) ||
303                   !(conf->dev.absmin[action] == -1)) {
304                         wminput_err("Warning: duplicate absolute axis assignment");
305                 }
306
307                 conf->dev.absmax[action] = plugin->info->axis_info[i].max;
308                 conf->dev.absmin[action] = plugin->info->axis_info[i].min;
309                 conf->dev.absfuzz[action] = plugin->info->axis_info[i].fuzz;
310                 conf->dev.absflat[action] = plugin->info->axis_info[i].flat;
311         }
312
313         return 0;
314 }
315
316 int conf_plugin_param_int(struct conf *conf, const char *name,
317                           const char *param, int value)
318 {
319         struct plugin *plugin;
320         int i;
321         unsigned char param_found = 0;
322
323         if ((plugin = get_plugin(conf, name)) == NULL) {
324                 return -1;
325         }
326
327         for (i=0; i < plugin->info->param_count; i++) {
328                 if (!strcmp(plugin->info->param_info[i].name, param)) {
329                         param_found = 1;
330                         break;
331                 }
332         }
333
334         if (!param_found) {
335                 wminput_err("Invalid plugin parameter: %s.%s", name, param);
336                 return -1;
337         }
338
339         switch (plugin->type) {
340         case PLUGIN_C:
341                 if (c_plugin_param_int(plugin, i, value)) {
342                         return -1;
343                 }
344                 break;
345         case PLUGIN_PYTHON:
346                 if (py_plugin_param_int(plugin, i, value)) {
347                         return -1;
348                 }
349                 break;
350         }
351
352         return 0;
353 }
354
355 int conf_plugin_param_float(struct conf *conf, const char *name,
356                             const char *param, float value)
357 {
358         struct plugin *plugin;
359         int i;
360         unsigned char param_found = 0;
361
362         if ((plugin = get_plugin(conf, name)) == NULL) {
363                 return -1;
364         }
365
366         for (i=0; i < plugin->info->param_count; i++) {
367                 if (!strcmp(plugin->info->param_info[i].name, param)) {
368                         param_found = 1;
369                         break;
370                 }
371         }
372
373         if (!param_found) {
374                 wminput_err("Invalid plugin parameter: %s.%s", name, param);
375                 return -1;
376         }
377
378         switch (plugin->type) {
379         case PLUGIN_C:
380                 if (c_plugin_param_float(plugin, i, value)) {
381                         return -1;
382                 }
383                 break;
384         case PLUGIN_PYTHON:
385                 if (py_plugin_param_float(plugin, i, value)) {
386                         return -1;
387                 }
388                 break;
389         }
390
391         return 0;
392 }
393
394 void conf_init(struct conf *conf)
395 {
396         int i, j;
397
398         conf->fd = -1;
399         conf->config_search_dirs = NULL;
400         conf->plugin_search_dirs = NULL;
401         conf->current_config_filename = NULL;
402         conf->stack_index = -1;
403         for (i=0; i < CONF_MAX_INCLUDE_DEPTH; i++) {
404                 conf->config_filename_stack[i] = NULL;
405         }
406         conf->rpt_mode_flags = 0;
407         memset(&conf->dev, 0, sizeof conf->dev);
408         strncpy(conf->dev.name, UINPUT_NAME, UINPUT_MAX_NAME_SIZE);
409         conf->dev.id.bustype = UINPUT_BUSTYPE;
410         conf->dev.id.vendor = UINPUT_VENDOR;
411         conf->dev.id.product = UINPUT_PRODUCT;
412         conf->dev.id.version = UINPUT_VERSION;
413         for (i=0; i < ABS_MAX; i++) {
414                 conf->dev.absmax[i] = -1;
415                 conf->dev.absmin[i] = -1;
416                 conf->dev.absfuzz[i] = -1;
417                 conf->dev.absflat[i] = -1;
418         }
419         conf->ff = 0;
420         conf->wiimote_bmap[CONF_WM_BTN_UP].mask = CWIID_BTN_UP;
421         conf->wiimote_bmap[CONF_WM_BTN_DOWN].mask = CWIID_BTN_DOWN;
422         conf->wiimote_bmap[CONF_WM_BTN_LEFT].mask = CWIID_BTN_LEFT;
423         conf->wiimote_bmap[CONF_WM_BTN_RIGHT].mask = CWIID_BTN_RIGHT;
424         conf->wiimote_bmap[CONF_WM_BTN_A].mask = CWIID_BTN_A;
425         conf->wiimote_bmap[CONF_WM_BTN_B].mask = CWIID_BTN_B;
426         conf->wiimote_bmap[CONF_WM_BTN_MINUS].mask = CWIID_BTN_MINUS;
427         conf->wiimote_bmap[CONF_WM_BTN_PLUS].mask = CWIID_BTN_PLUS;
428         conf->wiimote_bmap[CONF_WM_BTN_HOME].mask = CWIID_BTN_HOME;
429         conf->wiimote_bmap[CONF_WM_BTN_1].mask = CWIID_BTN_1;
430         conf->wiimote_bmap[CONF_WM_BTN_2].mask = CWIID_BTN_2;
431         conf->nunchuk_bmap[CONF_NC_BTN_C].mask = CWIID_NUNCHUK_BTN_C;
432         conf->nunchuk_bmap[CONF_NC_BTN_Z].mask = CWIID_NUNCHUK_BTN_Z;
433         conf->classic_bmap[CONF_CC_BTN_UP].mask = CWIID_CLASSIC_BTN_UP;
434         conf->classic_bmap[CONF_CC_BTN_DOWN].mask = CWIID_CLASSIC_BTN_DOWN;
435         conf->classic_bmap[CONF_CC_BTN_LEFT].mask = CWIID_CLASSIC_BTN_LEFT;
436         conf->classic_bmap[CONF_CC_BTN_RIGHT].mask = CWIID_CLASSIC_BTN_RIGHT;
437         conf->classic_bmap[CONF_CC_BTN_MINUS].mask = CWIID_CLASSIC_BTN_MINUS;
438         conf->classic_bmap[CONF_CC_BTN_PLUS].mask = CWIID_CLASSIC_BTN_PLUS;
439         conf->classic_bmap[CONF_CC_BTN_HOME].mask = CWIID_CLASSIC_BTN_HOME;
440         conf->classic_bmap[CONF_CC_BTN_A].mask = CWIID_CLASSIC_BTN_A;
441         conf->classic_bmap[CONF_CC_BTN_B].mask = CWIID_CLASSIC_BTN_B;
442         conf->classic_bmap[CONF_CC_BTN_X].mask = CWIID_CLASSIC_BTN_X;
443         conf->classic_bmap[CONF_CC_BTN_Y].mask = CWIID_CLASSIC_BTN_Y;
444         conf->classic_bmap[CONF_CC_BTN_ZL].mask = CWIID_CLASSIC_BTN_ZL;
445         conf->classic_bmap[CONF_CC_BTN_ZR].mask = CWIID_CLASSIC_BTN_ZR;
446         conf->classic_bmap[CONF_CC_BTN_L].mask = CWIID_CLASSIC_BTN_L;
447         conf->classic_bmap[CONF_CC_BTN_R].mask = CWIID_CLASSIC_BTN_R;
448         for (i=0; i < CONF_WM_BTN_COUNT; i++) {
449                 conf->wiimote_bmap[i].active = 0;
450         }
451         for (i=0; i < CONF_NC_BTN_COUNT; i++) {
452                 conf->nunchuk_bmap[i].active = 0;
453         }
454         for (i=0; i < CONF_CC_BTN_COUNT; i++) {
455                 conf->classic_bmap[i].active = 0;
456         }
457         for (i=0; i < CONF_AXIS_COUNT; i++) {
458                 conf->amap[i].active = 0;
459                 conf->amap[i].axis_type = -1;
460                 conf->amap[i].action = -1;
461                 conf->amap[i].flags = 0;
462         }
463         for (i=0; i < CONF_MAX_PLUGINS; i++) {
464                 conf->plugins[i].name = NULL;
465                 conf->plugins[i].rpt_mode_flags = 0;
466                 conf->plugins[i].prev_buttons = 0;
467                 for (j=0; j < WMPLUGIN_MAX_BUTTON_COUNT; j++) {
468                         conf->plugins[i].bmap[j].active = 0;
469                         conf->plugins[i].bmap[j].mask = 1<<i;
470                         conf->plugins[i].bmap[j].action = -1;
471                 }
472                 for (j=0; j < WMPLUGIN_MAX_AXIS_COUNT; j++) {
473                         conf->plugins[i].amap[j].active = 0;
474                         conf->plugins[i].amap[j].axis_type = -1;
475                         conf->plugins[i].amap[j].action = -1;
476                         conf->plugins[i].amap[j].flags = 0;
477                 }
478         }
479 }
480
481 #define CONF_PATHNAME_LEN       128
482 FILE *conf_push_config(struct conf *conf, const char *filename, YYLTYPE *yyloc)
483 {
484         int i;
485         FILE *file;
486         char pathname[CONF_PATHNAME_LEN];
487         const char *stackname;
488
489         if (conf->stack_index+1 >= CONF_MAX_INCLUDE_DEPTH) {
490                 wminput_err("maximum include depth exceeded: %s", filename);
491                 return NULL;
492         }
493
494         /* filename == / or ./ or ../ */
495         if ((filename[0] == '/') ||
496             ((filename[0] == '.') &&
497               ((filename[1] == '/') ||
498               ((filename[1] == '.') && (filename[2] == '/'))))) {
499                 stackname = filename;
500                 file = fopen(filename, "r");
501         }
502         else {
503                 for (i=0; conf->config_search_dirs[i]; i++) {
504                         snprintf(pathname, CONF_PATHNAME_LEN, "%s/%s",
505                                  conf->config_search_dirs[i], filename);
506                         if ((file = fopen(pathname, "r"))) {
507                                 stackname = pathname;
508                                 break;
509                         }
510                 }
511         }
512
513         if (!file) {
514                 wminput_err("file not found: %s", filename);
515                 return NULL;
516         }
517
518         conf->stack_index++;
519         if ((conf->config_filename_stack[conf->stack_index] =
520           malloc(strlen(stackname) + 1)) == NULL) {
521                 wminput_err("out of memory");
522                 conf->stack_index--;
523                 return NULL;
524         }
525         strcpy(conf->config_filename_stack[conf->stack_index], stackname);
526         if (yyloc) {
527                 conf->yyloc_stack[conf->stack_index] = *yyloc;
528         }
529
530         conf->current_config_filename =
531                 conf->config_filename_stack[conf->stack_index];
532
533         return file;
534 }
535
536 int conf_pop_config(struct conf *conf, YYLTYPE *yyloc)
537 {
538         if (conf->stack_index == -1) {
539                 return -1;
540         }
541
542         free(conf->config_filename_stack[conf->stack_index]);
543         *yyloc = conf->yyloc_stack[conf->stack_index];
544
545         conf->stack_index--;
546
547         conf->current_config_filename =
548                 conf->config_filename_stack[conf->stack_index];
549
550         return 0;
551 }
552
553 int lookup_action(const char *str_action)
554 {
555         int i=0;
556
557         while (action_enum[i].name) {
558                 if (!strcmp(str_action, action_enum[i].name)) {
559                         return action_enum[i].value;
560                 }
561                 i++;
562         }
563
564         return -1;
565 }
566
567 struct plugin *get_plugin(struct conf *conf, const char *name)
568 {
569         int i;
570         char plugin_found = 0;
571         struct plugin *plugin;
572
573         for (i=0; i < CONF_MAX_PLUGINS; i++) {
574                 if (!conf->plugins[i].name) {
575                         break;
576                 }
577                 else if (!strcmp(conf->plugins[i].name, name)) {
578                         return &conf->plugins[i];
579                 }
580         }
581
582         if (i == CONF_MAX_PLUGINS) {
583                 wminput_err("maximum number of plugins exceeded");
584                 return NULL;
585         }
586
587         plugin = &conf->plugins[i];
588         plugin->name = (char *)name;
589
590         for (i=0; conf->plugin_search_dirs[i]; i++) {
591                 if (!c_plugin_open(plugin, conf->plugin_search_dirs[i])) {
592                         plugin_found = 1;
593                         break;
594                 }
595                 if (!py_plugin_open(plugin, conf->plugin_search_dirs[i])) {
596                         plugin_found = 1;
597                         break;
598                 }
599         }
600
601         if (!plugin_found) {
602                 wminput_err("plugin not found: %s", name);
603                 free(plugin->name);
604                 plugin->name = NULL;
605                 return NULL;
606         }
607
608         return plugin;
609 }
Note: See TracBrowser for help on using the browser.