00001 /* 00002 * source-device.h 00003 * 00004 * Copyright (C) 2009-2011 Thomas A. Vaughan 00005 * All rights reserved. 00006 * 00007 * 00008 * Redistribution and use in source and binary forms, with or without 00009 * modification, are permitted provided that the following conditions are met: 00010 * * Redistributions of source code must retain the above copyright 00011 * notice, this list of conditions and the following disclaimer. 00012 * * Redistributions in binary form must reproduce the above copyright 00013 * notice, this list of conditions and the following disclaimer in the 00014 * documentation and/or other materials provided with the distribution. 00015 * * Neither the name of the <organization> nor the 00016 * names of its contributors may be used to endorse or promote products 00017 * derived from this software without specific prior written permission. 00018 * 00019 * THIS SOFTWARE IS PROVIDED BY THOMAS A. VAUGHAN ''AS IS'' AND ANY 00020 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 00021 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 00022 * DISCLAIMED. IN NO EVENT SHALL THOMAS A. VAUGHAN BE LIABLE FOR ANY 00023 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 00024 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 00025 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 00026 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00027 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00028 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00029 * 00030 * 00031 * Abstraction for a device that can act as the source of gamepad events. This 00032 * is often a wrapper around a particular USB adapter, for instance 00033 */ 00034 00035 #ifndef GAMEPAD_SOURCE_DEVICE_H__ 00036 #define GAMEPAD_SOURCE_DEVICE_H__ 00037 00038 // includes -------------------------------------------------------------------- 00039 #include "common/common.h" 00040 #include "threadsafe/smart_ptr.h" 00041 00042 00043 namespace gamepad { 00044 00045 00046 /// \ingroup gamepad_api 00047 /// \defgroup source_device Source Device Interface 00048 /// 00049 /// This library exists to abstract the gamepad library from physical input 00050 /// sources. You can use the gamepad library to map any input to a gamepad, 00051 /// so long as you supply an object that supports this interface. 00052 /// 00053 /// See linux_input for an example of a SourceDevice implemented on top of the 00054 /// linux input event model. 00055 /*@{*/ 00056 00057 00058 /// button state enum. Note that button state is somewhat tricky! Many (or 00059 /// most) source devices will give a full event history, so that every 00060 /// single button press will be recorded. But this interface uses polling 00061 /// rather than events, and therefore multiple button press events could 00062 /// be compressed into a single "button is down" result. 00063 /// If your game requires full eventing (capture every single button press 00064 /// regardless of polling interval) 00065 /// then you probably need to use raw input APIs directly. For most 00066 /// uses the eButtonWasPushed/eButtonWasReleased flags should be sufficient. 00067 enum eButton { 00068 // current state 00069 eButtonDown = 0x01, ///< button is pushed down right now 00070 eButtonUp = 0x00, ///< button is not pushed down now 00071 00072 // recent state 00073 eButtonWasPushed = 0x10, ///< button was pushed at one point 00074 eButtonWasReleased = 0x20, ///< button was released at one point 00075 00076 // handy masks 00077 eButtonWasOrIsDown = 0x11, ///< button was or is pushed down 00078 00079 // keep this last! 00080 eButtonInvalid = 0x80 00081 }; 00082 00083 00084 00085 /// device state enum. At the moment these are exclusive values, but other 00086 /// device flags may be supported in the future, so I recommend performing 00087 /// bit-check operations rather than checking for equality. 00088 /// "Attached" means that the device is capable of sending events, even if it 00089 /// isn't physically attached. For instance, a wireless or 00090 /// bluetooth device is considered attached if it is communicating 00091 /// with the local host. "Detached" means that the device has been 00092 /// physically disconnected and/or turned off so no more events can 00093 /// be retrieved. 00094 enum eDeviceState { 00095 00096 // attached state. These are exclusive values. 00097 eDevice_Attached = 0x0001, ///< device is properly attached 00098 eDevice_Detached = 0x0002, ///< device is definitely not attached 00099 eDevice_Unknown = 0x0004, ///< may or may not be attached--common! 00100 00101 // keep this last 00102 eDevice_Invalid = 0 00103 }; 00104 00105 00106 00107 /// what you get back when you read the value of a particular potentiometer 00108 struct pot_value_t { 00109 enum eConstants { 00110 eStartMin = (+1000) * (1000), 00111 eStartMax = (-1000) * (1000) 00112 }; 00113 00114 // constructor, manipulators 00115 pot_value_t(void) throw() { this->clear(); } 00116 void clear(void) throw() { 00117 minSeen = eStartMin; 00118 maxSeen = eStartMax; 00119 value = 0; 00120 } 00121 void dump(IN const char * title) const throw() { 00122 DPRINTF("%s val=%d [%d - %d]", 00123 title, value, minSeen, maxSeen); 00124 } 00125 bool isValid(void) const throw() { 00126 return (minSeen < maxSeen && 00127 value >= minSeen && 00128 value <= maxSeen); 00129 } 00130 void update(IN int newValue) throw() { 00131 value = newValue; 00132 if (value < minSeen) 00133 minSeen = value; 00134 if (value > maxSeen) 00135 maxSeen = value; 00136 } 00137 00138 // data fields 00139 int minSeen; ///< minimum value seen 00140 int maxSeen; ///< maximum value seen 00141 int value; ///< current (most recent) value 00142 }; 00143 00144 00145 00146 /// helper method to update a button value. Given an input set of eButton 00147 /// bit flags, and the current button state (up or down), returns a new 00148 /// set of button bit flags. 00149 byte_t updateButton(IN byte_t oldBitFlags, IN bool isButtonDown) throw(); 00150 00151 00152 00153 /// An object that supplies gamepad input. Often this is a USB device, for 00154 /// instance, that may support multiple different types of gamepads plugged in 00155 /// at once. Regardless of how many gamepads are plugged in, a SourceDevice 00156 /// is supposed to represent a physical or logical device (USB device or the 00157 /// bluetooth subsystem as respective examples) that supports polling 00158 /// independent of other SourceDevice objects. 00159 /// 00160 /// Force feedback support is purposely limited for now. If you want rich 00161 /// force feedback support, you should probably work closer to the native 00162 /// drivers. 00163 class SourceDevice { 00164 public: 00165 // virtual destructor -------------------------------------------------- 00166 virtual ~SourceDevice(void) throw(); 00167 00168 // gamepad::SourceDevice class interface methods ----------------------- 00169 00170 /// a "pretty" name, often the manufacturer and model, for instance. 00171 /// note that this is recommended for debugging but not necessarily 00172 /// for display to the end gamer (string may not be meaningful, and 00173 /// almost certainly isn't localized). 00174 /// \b NOTE: this should come directly from the hardware itself, and 00175 /// not be modified by any code. This gives developers a chance to 00176 /// identify hardware by name. 00177 /// \b WARNING: despite what I just said, be careful about identifying 00178 /// hardware by public name. In testing, I've found many USB adaptors 00179 /// have the same hardware-specified information, even though they 00180 /// behave quite differently. So only use the public name for 00181 /// devices you know will have consistent behavior. In practice, this 00182 /// will tend to be gamepads that directly attach via USB and not 00183 /// adaptors (for instance, XBox 360 and Playstation3 controllers). 00184 virtual const char * getPublicName(void) throw() = 0; 00185 00186 /// each source device MUST supply a unique ID. The ID must be unique 00187 /// to that physical device, not just the manufacturer and model! 00188 /// So for instance if a gamer plugged in two identical USB 00189 /// adapters, the unique ID would still be different for each. 00190 /// Sometimes (rarely) manufacturers make the serial number of their 00191 /// adapters/joysticks available. Barring that, anyone who 00192 /// implements this interface has to ensure the IDs are unique. 00193 /// These IDs should be unique for the lifetime of the device (this 00194 /// process) but are not generally valid across process lifetimes, 00195 /// and so should not be persisted. 00196 virtual const char * getUniqueId(void) throw() = 0; 00197 00198 /// returns the current state of the source device. Note that many 00199 /// sources aren't capable of determining whether or not they are 00200 /// attached! This is annoying but reflects either poor standards 00201 /// or the physical realities of the device in question. 00202 /// If someone disconnects a gamepad (or turns it off in the case of 00203 /// wireless gamepads) you'll stop receiving events and the poll() 00204 /// call won't actually do anything. 00205 /// Call this method occasionally so you can detect when a player has 00206 /// disconnected a device. 00207 virtual eDeviceState getState(void) throw() = 0; 00208 00209 /// the source must say how many pots (potentiometers) are exposed. A 00210 /// "pot" is any input that allows the user to continuously vary it 00211 /// through a range of values. An example is the X or Y axis of a 00212 /// joystick, or a single axis in the case of steering wheels. 00213 /// See http://en.wikipedia.org/wiki/Potentiometer 00214 /// This is the total number of pots supported by the source device, NOT 00215 /// the number of pots per gamepad (the two numbers will often be 00216 /// the same for single-gamepad devices). 00217 virtual int getNumPots(void) throw() = 0; 00218 00219 /// the source must say how many buttons are exposed. This is the total 00220 /// number of buttons for the source device, NOT the number of 00221 /// buttons per gamepad (again, some source devices may support 00222 /// multiple gamepads). 00223 virtual int getNumButtons(void) throw() = 0; 00224 00225 /* 00226 // Jan 2011: removing all force feedback support for now 00227 /// the source must say how many force feedback rumble objects are 00228 /// supported. Typically there are one per gamepad, for instance. 00229 //virtual int getNumRumblers(void) throw() = 0; 00230 */ 00231 00232 /// the source will be asked to poll all of its inputs. This is so 00233 /// that later calls to getPotValue() or getButtonValue() will 00234 /// return the current value. 00235 virtual void poll(void) throw() = 0; 00236 00237 /// retrieves the value of a particular potentiometer. 00238 virtual const pot_value_t& getPotValue(IN int potIndex) = 0; 00239 00240 /// retrieves the state of a particular button. Typically this is 00241 /// eButtonDown or eButtonUp, maybe OR'd with eButtonWasPushed 00242 /// if the button was ever pushed between this and the previous 00243 /// poll interval. See the eButton enum. 00244 virtual eButton getButtonValue(IN int buttonIndex) = 0; 00245 00246 /* 00247 // Jan 2011: removing all force feedback support for now 00248 /// plays the given rumbler effect. Returns false on failure 00249 virtual bool playRumble(IN int rumbleIndex, 00250 IN uint16_t highFreqMagnitude, 00251 IN uint16_t lowFreqMagnitude, 00252 IN int durationMilliseconds) = 0; 00253 */ 00254 }; 00255 00256 00257 00258 /// objects supporting this interface can create gamepad::SourceDevice 00259 /// instances. 00260 /// Note to implementers (and users): objects supporting this interface are 00261 /// intended to be long-lived. So if you write an object that supports this 00262 /// interface, it should re-poll (or do whatever discovery is necessary) on 00263 /// every API call, and not rely on one-time discovery during object 00264 /// initialization. In particular, it is expected that 00265 /// SourceDeviceFactory::getCount() will be expensive to call. 00266 class SourceDeviceFactory { 00267 public: 00268 // virtual destructor -------------------------------------------------- 00269 virtual ~SourceDeviceFactory(void) throw(); 00270 00271 // gamepad::SourceDeviceFactory class interface methods ---------------- 00272 virtual const char * getName(void) const throw() = 0; 00273 virtual int getCount(void) = 0; 00274 virtual smart_ptr<SourceDevice> getSourceDevice(IN int index) = 0; 00275 }; 00276 00277 00278 00279 /// state snapshot of a source device. Used by configuration tools only 00280 struct device_state_t { 00281 // enums 00282 enum eConstants { 00283 eMaxButtons = 256, 00284 eMaxPots = 256 00285 }; 00286 00287 // constructor, manipulators 00288 device_state_t(void) throw() { this->clear(); } 00289 void clear(void) throw() { 00290 nPots = nButtons = 0; 00291 } 00292 void dump(IN const char * title) const throw() { 00293 DPRINTF("%s (source device state snapshot)", title); 00294 DPRINTF(" Number of potentiometers: %d", nPots); 00295 DPRINTF(" Number of buttons: %d", nButtons); 00296 } 00297 00298 // data fields 00299 int nPots; 00300 int nButtons; 00301 int button[eMaxButtons]; 00302 pot_value_t pot[eMaxPots]; 00303 }; 00304 00305 00306 00307 /// take a state snapshot 00308 void snapshotState(IN SourceDevice * device, 00309 OUT device_state_t& state); 00310 00311 00312 /// is a single button down? 00313 int buttonDown(IN const device_state_t& state); 00314 00315 00316 /// was a button released? 00317 int buttonReleased(IN const device_state_t& state); 00318 00319 00320 /// compare new and old states: did a single button change state? 00321 int buttonChanged(IN const device_state_t& oldState, 00322 IN const device_state_t& newState); 00323 00324 00325 /// compare new and old states: are all potentiometers calibrated? 00326 bool potsCalibrated(IN const device_state_t& oldState, 00327 IN const device_state_t& newState); 00328 00329 00330 /// get pot at largest value--specify threshold: 0 (min) to 1 (max). 00331 /// pots with values under the threshold will be ignored. 00332 int maxPotValue(IN const device_state_t& state, 00333 IN float threshold); 00334 00335 00336 /// compare new and old states: which potentiometer has changed most? 00337 int maxPotChanged(IN const device_state_t& oldState, 00338 IN const device_state_t& newState); 00339 00340 00341 }; // gamepad namespace 00342 00343 #endif // GAMEPAD_SOURCE_DEVICE_H__ 00344