1 /* bzflag
2  * Copyright (c) 1993-2021 Tim Riker
3  *
4  * This package is free software;  you can redistribute it and/or
5  * modify it under the terms of the license found in the file
6  * named COPYING that should have accompanied this file.
7  *
8  * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
9  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
10  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
11  */
12 
13 /* EvdevJoystick:
14  *  Encapsulates a joystick accessed via a linux event device.
15  *      This is basically equivalent to what SDL does on linux, but we
16  *      have the added bonus of supporting force feedback where SDL
17  *      does not.
18  *
19  *      SDL does not yet support force feedback, and there is no good
20  *      way to graft linux-specific force feedback support onto SDL-
21  *      so we just do it all ourselves without even initializing SDL's
22  *      joystick support.
23  */
24 
25 #ifndef BZF_EVDEV_JOY_H
26 #define BZF_EVDEV_JOY_H
27 
28 #include "BzfJoystick.h"
29 #include <map>
30 #include <string>
31 #include <vector>
32 
33 struct EvdevJoystickInfo
34 {
35     /* Information about a joystick that's installed on the
36      * system but not necessarily the one we're using. This
37      * is collected at EvdevJoystick initialization time.
38      */
39 
40     std::string filename;
41 
42     /* Bits describing the capabilities of this device. linux/input.h
43      * includes macros and constants necessary to get useful info
44      * out of this.
45      */
46     unsigned long evbit [16];
47     unsigned long keybit[64];
48     unsigned long absbit[16];
49     unsigned long ffbit [16];
50 
51     struct
52     {
53         int value;
54         int minimum;
55         int maximum;
56         int fuzz;
57         int flat;
58     } axis_info[9];
59 
60     /* if we can only read from this joystick, remember that */
61     bool readonly;
62 };
63 
64 class EvdevJoystick : public BzfJoystick
65 {
66 public:
67     EvdevJoystick();
68     ~EvdevJoystick();
69 
70     void    initJoystick(const char* joystickName);
71     bool    joystick() const;
72     void    getJoy(int& x, int& y);
73     int  getNumHats();
74     void    getJoyHat(int hat, float &hatX, float &hatY);
75     unsigned long getJoyButtons();
76     void    getJoyDevices(std::vector<std::string> &list) const;
77 
78     void    getJoyDeviceAxes(std::vector<std::string> &list) const;
79     void    setXAxis(const std::string &axis);
80     void    setYAxis(const std::string &axis);
81 
82     bool    ffHasRumble() const;
83     void    ffRumble(int count,
84                      float delay, float duration,
85                      float strong_motor, float weak_motor=0.0f);
86 
87     bool    ffHasDirectional() const;
88     void    ffDirectionalConstant(int count,
89                                   float delay, float duration,
90                                   float x_direction, float y_direction,
91                                   float strength);
92     void    ffDirectionalPeriodic(int count,
93                                   float delay, float duration,
94                                   float x_direction, float y_direction,
95                                   float amplitude, float period,
96                                   PeriodicType type);
97     void    ffDirectionalResistance(float time, float coefficient,
98                                     float saturation, ResistanceType type);
99 
100     /* Test whether this driver should be used without actually
101      * loading it. Will return false if no event devices can be
102      * located, or if it has been specifically disabled by setting
103      * the environment variable BZFLAG_ENABLE_EVDEV=0
104      */
105     static bool isEvdevAvailable();
106 
107 private:
108     static void scanForJoysticks(std::map<std::string,EvdevJoystickInfo> &joysticks);
109     static bool collectJoystickBits(int fd, struct EvdevJoystickInfo &info);
110     static bool isJoystick(struct EvdevJoystickInfo &info);
111 
112     void    poll();
113     void    setButton(int button_num, int state);
114     int  mapButton(int bit_num);
115     void    ffResetEffect();
116     void    writeJoystick(int count);
117 
118     std::map<std::string,EvdevJoystickInfo> joysticks;
119 
120     int     useaxis[2];
121     EvdevJoystickInfo*    currentJoystick;
122     int          joystickfd;
123     int          buttons;
124     int       numHats;
125     std::vector<float>   hataxes;
126     struct ff_effect*      ff_rumble;
127 };
128 
129 // The drivers don't define a minimum delay that I can tell.  This seems to work.
130 #define FF_NOMINAL_MIN 0x10;
131 
132 #endif // BZF_EVDEV_JOY_H
133 
134 // Local Variables: ***
135 // mode: C++ ***
136 // tab-width: 4 ***
137 // c-basic-offset: 4 ***
138 // indent-tabs-mode: nil ***
139 // End: ***
140 // ex: shiftwidth=4 tabstop=4
141