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