Ver Fonte

Added stubs for simple Steam Controller support

Sam Lantinga há 7 anos atrás
pai
commit
d828647944

+ 5 - 1
Android.mk

@@ -31,6 +31,8 @@ LOCAL_SRC_FILES := \
 	$(wildcard $(LOCAL_PATH)/src/haptic/android/*.c) \
 	$(wildcard $(LOCAL_PATH)/src/joystick/*.c) \
 	$(wildcard $(LOCAL_PATH)/src/joystick/android/*.c) \
+	$(LOCAL_PATH)/src/joystick/steam/SDL_steamcontroller.c \
+	$(LOCAL_PATH)/src/joystick/steam/steamcontroller_hidapi.c \
 	$(wildcard $(LOCAL_PATH)/src/loadso/dlopen/*.c) \
 	$(wildcard $(LOCAL_PATH)/src/power/*.c) \
 	$(wildcard $(LOCAL_PATH)/src/power/android/*.c) \
@@ -44,7 +46,9 @@ LOCAL_SRC_FILES := \
 	$(wildcard $(LOCAL_PATH)/src/timer/unix/*.c) \
 	$(wildcard $(LOCAL_PATH)/src/video/*.c) \
 	$(wildcard $(LOCAL_PATH)/src/video/android/*.c) \
-	$(wildcard $(LOCAL_PATH)/src/test/*.c))
+	$(wildcard $(LOCAL_PATH)/src/test/*.c)) \
+
+LOCAL_SHARED_LIBRARIES := hidapi
 
 LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES
 LOCAL_LDLIBS := -ldl -lGLESv1_CM -lGLESv2 -llog -landroid

+ 16 - 0
Xcode-iOS/SDL/SDL.xcodeproj/project.pbxproj

@@ -90,6 +90,8 @@
 		56F9D5601DF73BA400C15B5D /* SDL_dataqueue.c in Sources */ = {isa = PBXBuildFile; fileRef = 566726431DF72CF5001DD3DB /* SDL_dataqueue.c */; };
 		93CB792313FC5E5200BD3E05 /* SDL_uikitviewcontroller.h in Headers */ = {isa = PBXBuildFile; fileRef = 93CB792213FC5E5200BD3E05 /* SDL_uikitviewcontroller.h */; };
 		93CB792613FC5F5300BD3E05 /* SDL_uikitviewcontroller.m in Sources */ = {isa = PBXBuildFile; fileRef = 93CB792513FC5F5300BD3E05 /* SDL_uikitviewcontroller.m */; };
+		A7A9EEA91F702631002A5589 /* SDL_steamcontroller.c in Sources */ = {isa = PBXBuildFile; fileRef = A7A9EEA71F702631002A5589 /* SDL_steamcontroller.c */; };
+		A7A9EEAA1F702631002A5589 /* SDL_steamcontroller.h in Headers */ = {isa = PBXBuildFile; fileRef = A7A9EEA81F702631002A5589 /* SDL_steamcontroller.h */; };
 		AA0AD06216647BBB00CE5896 /* SDL_gamecontroller.c in Sources */ = {isa = PBXBuildFile; fileRef = AA0AD06116647BBB00CE5896 /* SDL_gamecontroller.c */; };
 		AA0AD06516647BD400CE5896 /* SDL_gamecontroller.h in Headers */ = {isa = PBXBuildFile; fileRef = AA0AD06416647BD400CE5896 /* SDL_gamecontroller.h */; };
 		AA0F8495178D5F1A00823F9D /* SDL_systls.c in Sources */ = {isa = PBXBuildFile; fileRef = AA0F8494178D5F1A00823F9D /* SDL_systls.c */; };
@@ -393,6 +395,8 @@
 		56ED04E2118A8EFD00A56AA6 /* SDL_syspower.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SDL_syspower.m; path = ../../src/power/uikit/SDL_syspower.m; sourceTree = SOURCE_ROOT; };
 		93CB792213FC5E5200BD3E05 /* SDL_uikitviewcontroller.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_uikitviewcontroller.h; sourceTree = "<group>"; };
 		93CB792513FC5F5300BD3E05 /* SDL_uikitviewcontroller.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDL_uikitviewcontroller.m; sourceTree = "<group>"; };
+		A7A9EEA71F702631002A5589 /* SDL_steamcontroller.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_steamcontroller.c; sourceTree = "<group>"; };
+		A7A9EEA81F702631002A5589 /* SDL_steamcontroller.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_steamcontroller.h; sourceTree = "<group>"; };
 		AA0AD06116647BBB00CE5896 /* SDL_gamecontroller.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_gamecontroller.c; sourceTree = "<group>"; };
 		AA0AD06416647BD400CE5896 /* SDL_gamecontroller.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_gamecontroller.h; sourceTree = "<group>"; };
 		AA0F8494178D5F1A00823F9D /* SDL_systls.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_systls.c; sourceTree = "<group>"; };
@@ -725,6 +729,15 @@
 			name = uikit;
 			sourceTree = "<group>";
 		};
+		A7A9EEA61F702607002A5589 /* steam */ = {
+			isa = PBXGroup;
+			children = (
+				A7A9EEA71F702631002A5589 /* SDL_steamcontroller.c */,
+				A7A9EEA81F702631002A5589 /* SDL_steamcontroller.h */,
+			);
+			path = steam;
+			sourceTree = "<group>";
+		};
 		FD3F4A6F0DEA620800C5B771 /* stdlib */ = {
 			isa = PBXGroup;
 			children = (
@@ -742,6 +755,7 @@
 		FD5F9D080E0E08B3008E885B /* joystick */ = {
 			isa = PBXGroup;
 			children = (
+				A7A9EEA61F702607002A5589 /* steam */,
 				FD689EFF0E26E5B600F90B21 /* iphoneos */,
 				AA0AD06116647BBB00CE5896 /* SDL_gamecontroller.c */,
 				FD5F9D1E0E0E08B3008E885B /* SDL_joystick.c */,
@@ -1124,6 +1138,7 @@
 				04F7807E12FB751400FC43C0 /* SDL_drawline.h in Headers */,
 				04F7808012FB751400FC43C0 /* SDL_drawpoint.h in Headers */,
 				04F7808412FB753F00FC43C0 /* SDL_nullframebuffer_c.h in Headers */,
+				A7A9EEAA1F702631002A5589 /* SDL_steamcontroller.h in Headers */,
 				0442EC5012FE1C1E004C9285 /* SDL_render_sw_c.h in Headers */,
 				FA1DC2721C62BE65008F99A0 /* SDL_uikitclipboard.h in Headers */,
 				0402A85A12FE70C600CECEE3 /* SDL_shaders_gles2.h in Headers */,
@@ -1398,6 +1413,7 @@
 			files = (
 				FD6526810DE8FCDD002AD96B /* SDL_systimer.c in Sources */,
 				FD6526800DE8FCDD002AD96B /* SDL_timer.c in Sources */,
+				A7A9EEA91F702631002A5589 /* SDL_steamcontroller.c in Sources */,
 				FD3F4A7B0DEA620800C5B771 /* SDL_string.c in Sources */,
 				FD6526660DE8FCDD002AD96B /* SDL_dummyaudio.c in Sources */,
 				FD6526670DE8FCDD002AD96B /* SDL_audio.c in Sources */,

+ 2 - 0
configure

@@ -16846,6 +16846,7 @@ fi
 SOURCES="$SOURCES $srcdir/src/*.c"
 SOURCES="$SOURCES $srcdir/src/atomic/*.c"
 SOURCES="$SOURCES $srcdir/src/audio/*.c"
+SOURCES="$SOURCES $srcdir/src/audio/marvell/*.c"
 SOURCES="$SOURCES $srcdir/src/cpuinfo/*.c"
 SOURCES="$SOURCES $srcdir/src/dynapi/*.c"
 SOURCES="$SOURCES $srcdir/src/events/*.c"
@@ -23839,6 +23840,7 @@ $as_echo "#define SDL_AUDIO_DRIVER_ANDROID 1" >>confdefs.h
 $as_echo "#define SDL_JOYSTICK_LINUX 1" >>confdefs.h
 
                 SOURCES="$SOURCES $srcdir/src/joystick/linux/*.c"
+                SOURCES="$SOURCES $srcdir/src/joystick/steam/*.c"
                 have_joystick=yes
             ;;
             android)

+ 2 - 0
configure.in

@@ -325,6 +325,7 @@ fi
 SOURCES="$SOURCES $srcdir/src/*.c"
 SOURCES="$SOURCES $srcdir/src/atomic/*.c"
 SOURCES="$SOURCES $srcdir/src/audio/*.c"
+SOURCES="$SOURCES $srcdir/src/audio/marvell/*.c"
 SOURCES="$SOURCES $srcdir/src/cpuinfo/*.c"
 SOURCES="$SOURCES $srcdir/src/dynapi/*.c"
 SOURCES="$SOURCES $srcdir/src/events/*.c"
@@ -3360,6 +3361,7 @@ case "$host" in
             linux)
                 AC_DEFINE(SDL_JOYSTICK_LINUX, 1, [ ])
                 SOURCES="$SOURCES $srcdir/src/joystick/linux/*.c"
+                SOURCES="$SOURCES $srcdir/src/joystick/steam/*.c"
                 have_joystick=yes
             ;;
             android)

+ 27 - 0
src/joystick/SDL_gamecontroller.c

@@ -33,6 +33,11 @@
 #include "../events/SDL_events_c.h"
 #endif
 
+#if defined(__ANDROID__)
+#include "SDL_system.h"
+#endif
+
+
 #define SDL_CONTROLLER_PLATFORM_FIELD "platform:"
 
 /* a list of currently opened game controllers */
@@ -1157,12 +1162,30 @@ SDL_GameControllerLoadHints()
     }
 }
 
+/*
+ * Fill the given buffer with the expected controller mapping filepath. 
+ * Usually this will just be CONTROLLER_MAPPING_FILE, but for Android,
+ * we want to get the internal storage path.
+ */
+static SDL_bool SDL_GetControllerMappingFilePath(char *path, size_t size)
+{
+#ifdef CONTROLLER_MAPPING_FILE
+#define STRING(X) SDL_STRINGIFY_ARG(X)
+    return SDL_strlcpy(path, STRING(CONTROLLER_MAPPING_FILE), size) < size;
+#elif defined(__ANDROID__)
+    return SDL_snprintf(path, size, "%s/controller_map.txt", SDL_AndroidGetInternalStoragePath()) < size;
+#else
+    return SDL_FALSE;
+#endif
+}
+
 /*
  * Initialize the game controller system, mostly load our DB of controller config mappings
  */
 int
 SDL_GameControllerInitMappings(void)
 {
+    char szControllerMapPath[1024];
     int i = 0;
     const char *pMappingString = NULL;
     pMappingString = s_ControllerMappings[i];
@@ -1173,6 +1196,10 @@ SDL_GameControllerInitMappings(void)
         pMappingString = s_ControllerMappings[i];
     }
 
+    if (SDL_GetControllerMappingFilePath(szControllerMapPath, sizeof(szControllerMapPath))) {
+        SDL_GameControllerAddMappingsFromFile(szControllerMapPath);        
+    }
+
     /* load in any user supplied config */
     SDL_GameControllerLoadHints();
 

+ 11 - 2
src/joystick/SDL_gamecontrollerdb.h

@@ -191,6 +191,10 @@ static const char *s_ControllerMappings [] =
     "03000000a30600000cff000010010000,Saitek P2500 Force Rumble Pad,a:b2,b:b3,back:b11,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a2,x:b0,y:b1,",
     "03000000a30600000b04000000010000,Saitek P990 Dual Analog Pad,a:b1,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b8,x:b0,y:b3,",
     "03000000de2800000211000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,",
+    "05000000de2800000511000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,",
+    "03000000de2800000112000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,",
+    "05000000de2800000212000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,",
+    "03000000de2800004211000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,",
     "03000000de280000fc11000001000000,Steam Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,",
     "03000000de280000ff11000001000000,Steam Virtual Gamepad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,",
     "xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,",
@@ -201,13 +205,18 @@ static const char *s_ControllerMappings [] =
     "03000000830500006020000010010000,iBuffalo SNES Controller,a:b1,b:b0,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b7,x:b3,y:b2,",
 #endif
 #if defined(__ANDROID__)
+    "64633436313965656664373634323364,Microsoft X-Box 360 pad,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,x:b2,y:b3,",
     "4e564944494120436f72706f72617469,NVIDIA Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,",
+    "61363931656135336130663561616264,NVIDIA Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,",
+    "37336435666338653565313731303834,NVIDIA Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,",
+    "35643031303033326130316330353564,PS4 Controller,a:b1,b:b17,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b3,leftstick:b4,lefttrigger:+a3,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b6,righttrigger:+a4,rightx:a2,righty:a5,start:b16,x:b0,y:b2,",
+    "05000000de2800000511000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,",
+    "34356136633366613530316338376136,Xbox Wireless Controller,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b3,leftstick:b15,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b16,righttrigger:a5,rightx:a3,righty:a4,x:b17,y:b2,",
 #endif
 #if defined(SDL_JOYSTICK_MFI)
     "4d466947616d65706164010000000000,MFi Extended Gamepad,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b2,y:b3,",
     "4d466947616d65706164020000000000,MFi Gamepad,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,rightshoulder:b5,start:b6,x:b2,y:b3,",
-    "03000000de2800000211000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,",
-    "03000000de280000fc11000001000000,Steam Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,",
+    "05000000de2800000511000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,",
 #endif
 #if defined(SDL_JOYSTICK_EMSCRIPTEN)
     "emscripten,Standard Gamepad,a:b0,b:b1,back:b8,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,guide:b16,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,",

+ 117 - 27
src/joystick/android/SDL_sysjoystick.c

@@ -35,6 +35,7 @@
 #include "SDL_sysjoystick_c.h"
 #include "../SDL_joystick_c.h"
 #include "../../core/android/SDL_android.h"
+#include "../steam/SDL_steamcontroller.h"
 
 #include "android/keycodes.h"
 
@@ -216,7 +217,7 @@ Android_OnJoy(int device_id, int axis, float value)
     /* Android gives joy info normalized as [-1.0, 1.0] or [0.0, 1.0] */
     SDL_joylist_item *item = JoystickByDeviceId(device_id);
     if (item && item->joystick) {
-        SDL_PrivateJoystickAxis(item->joystick, axis, (Sint16) (32767.*value) );
+        SDL_PrivateJoystickAxis(item->joystick, axis, (Sint16) (32767.*value));
     }
     
     return 0;
@@ -234,7 +235,7 @@ Android_OnHat(int device_id, int hat_id, int x, int y)
     if (x >= -1 && x <=1 && y >= -1 && y <= 1) {
         SDL_joylist_item *item = JoystickByDeviceId(device_id);
         if (item && item->joystick) {
-            SDL_PrivateJoystickHat(item->joystick, hat_id, position_map[y+1][x+1] );
+            SDL_PrivateJoystickHat(item->joystick, hat_id, position_map[y+1][x+1]);
         }
         return 0;
     }
@@ -254,8 +255,8 @@ Android_AddJoystick(int device_id, const char *name, const char *desc, SDL_bool
     }
     
     /* the GUID is just the first 16 chars of the name for now */
-    SDL_zero( guid );
-    SDL_memcpy( &guid, desc, SDL_min( sizeof(guid), SDL_strlen( desc) ) );
+    SDL_zero(guid);
+    SDL_memcpy(&guid, desc, SDL_min(sizeof(guid), SDL_strlen(desc)));
 
     item = (SDL_joylist_item *) SDL_malloc(sizeof (SDL_joylist_item));
     if (item == NULL) {
@@ -266,7 +267,7 @@ Android_AddJoystick(int device_id, const char *name, const char *desc, SDL_bool
     item->guid = guid;
     item->device_id = device_id;
     item->name = SDL_strdup(name);
-    if ( item->name == NULL ) {
+    if (item->name == NULL) {
          SDL_free(item);
          return -1;
     }
@@ -349,6 +350,79 @@ Android_RemoveJoystick(int device_id)
 }
 
 
+static SDL_bool SteamControllerConnectedCallback(const char *name, SDL_JoystickGUID guid, int *device_instance)
+{
+    SDL_joylist_item *item;
+    
+    item = (SDL_joylist_item *)SDL_calloc(1, sizeof (SDL_joylist_item));
+    if (item == NULL) {
+        return SDL_FALSE;
+    }
+
+    *device_instance = item->device_instance = instance_counter++;
+    item->device_id = -1;
+    item->name = SDL_strdup(name);
+    item->guid = guid;
+    SDL_GetSteamControllerInputs(&item->nbuttons,
+                                 &item->naxes,
+                                 &item->nhats);
+    item->m_bSteamController = SDL_TRUE;
+
+    if (SDL_joylist_tail == NULL) {
+        SDL_joylist = SDL_joylist_tail = item;
+    } else {
+        SDL_joylist_tail->next = item;
+        SDL_joylist_tail = item;
+    }
+
+    /* Need to increment the joystick count before we post the event */
+    ++numjoysticks;
+
+    SDL_PrivateJoystickAdded(numjoysticks - 1);
+
+    return SDL_TRUE;
+}
+
+static void SteamControllerDisconnectedCallback(int device_instance)
+{
+    SDL_joylist_item *item = SDL_joylist;
+    SDL_joylist_item *prev = NULL;
+    
+    while (item != NULL) {
+        if (item->device_instance == device_instance) {
+            break;
+        }
+        prev = item;
+        item = item->next;
+    }
+    
+    if (item == NULL) {
+        return;
+    }
+
+    if (item->joystick) {
+        item->joystick->hwdata = NULL;
+    }
+        
+    if (prev != NULL) {
+        prev->next = item->next;
+    } else {
+        SDL_assert(SDL_joylist == item);
+        SDL_joylist = item->next;
+    }
+    if (item == SDL_joylist_tail) {
+        SDL_joylist_tail = prev;
+    }
+
+    /* Need to decrement the joystick count before we post the event */
+    --numjoysticks;
+
+    SDL_PrivateJoystickRemoved(item->device_instance);
+
+    SDL_free(item->name);
+    SDL_free(item);
+}
+
 int
 SDL_SYS_JoystickInit(void)
 {
@@ -359,6 +433,9 @@ SDL_SYS_JoystickInit(void)
         Android_AddJoystick(ANDROID_ACCELEROMETER_DEVICE_ID, ANDROID_ACCELEROMETER_NAME, ANDROID_ACCELEROMETER_NAME, SDL_TRUE, 0, 3, 0, 0);
     }
    
+    SDL_InitSteamControllers(SteamControllerConnectedCallback,
+                             SteamControllerDisconnectedCallback);
+
     return (numjoysticks);
 
 }
@@ -381,6 +458,8 @@ SDL_SYS_JoystickDetect(void)
         timeout = SDL_GetTicks() + 3000;
         Android_JNI_PollInputDevices();
     }
+
+    SDL_UpdateSteamControllers();
 }
 
 static SDL_joylist_item *
@@ -449,7 +528,7 @@ SDL_SYS_JoystickOpen(SDL_Joystick * joystick, int device_index)
 {
     SDL_joylist_item *item = JoystickByDevIndex(device_index);
 
-    if (item == NULL ) {
+    if (item == NULL) {
         return SDL_SetError("No such device");
     }
     
@@ -477,30 +556,34 @@ SDL_bool SDL_SYS_JoystickAttached(SDL_Joystick *joystick)
 void
 SDL_SYS_JoystickUpdate(SDL_Joystick * joystick)
 {
-    int i;
-    Sint16 value;
-    float values[3];
-    SDL_joylist_item *item = SDL_joylist;
+    SDL_joylist_item *item = (SDL_joylist_item *) joystick->hwdata;
 
-    while (item) {
-        if (item->is_accelerometer) {
-            if (item->joystick) {
-                if (Android_JNI_GetAccelerometerValues(values)) {
-                    for ( i = 0; i < 3; i++ ) {
-                        if (values[i] > 1.0f) {
-                            values[i] = 1.0f;
-                        } else if (values[i] < -1.0f) {
-                            values[i] = -1.0f;
-                        }
-
-                        value = (Sint16)(values[i] * 32767.0f);
-                        SDL_PrivateJoystickAxis(item->joystick, i, value);
-                    }
+    if (item == NULL) {
+        return;
+    }
+ 
+    if (item->m_bSteamController) {
+        SDL_UpdateSteamController(joystick);
+        return;
+    }
+
+    if (item->is_accelerometer) {
+        int i;
+        Sint16 value;
+        float values[3];
+
+        if (Android_JNI_GetAccelerometerValues(values)) {
+            for (i = 0; i < 3; i++) {
+                if (values[i] > 1.0f) {
+                    values[i] = 1.0f;
+                } else if (values[i] < -1.0f) {
+                    values[i] = -1.0f;
                 }
+
+                value = (Sint16)(values[i] * 32767.0f);
+                SDL_PrivateJoystickAxis(item->joystick, i, value);
             }
-            break;
         }
-        item = item->next;
     }
 }
 
@@ -518,6 +601,10 @@ SDL_SYS_JoystickClose(SDL_Joystick * joystick)
 void
 SDL_SYS_JoystickQuit(void)
 {
+/* We don't have any way to scan for joysticks at init, so don't wipe the list
+ * of joysticks here in case this is a reinit.
+ */
+#if 0
     SDL_joylist_item *item = NULL;
     SDL_joylist_item *next = NULL;
 
@@ -531,9 +618,12 @@ SDL_SYS_JoystickQuit(void)
 
     numjoysticks = 0;
     instance_counter = 0;
+#endif /* 0 */
+
+    SDL_QuitSteamControllers();
 }
 
-SDL_JoystickGUID SDL_SYS_JoystickGetDeviceGUID( int device_index )
+SDL_JoystickGUID SDL_SYS_JoystickGetDeviceGUID(int device_index)
 {
     return JoystickByDevIndex(device_index)->guid;
 }

+ 3 - 0
src/joystick/android/SDL_sysjoystick_c.h

@@ -46,6 +46,9 @@ typedef struct SDL_joylist_item
     SDL_Joystick *joystick;
     int nbuttons, naxes, nhats, nballs;
     
+    /* Steam Controller support */
+    SDL_bool m_bSteamController;
+
     struct SDL_joylist_item *next;
 } SDL_joylist_item;
 

+ 59 - 1
src/joystick/iphoneos/SDL_sysjoystick.m

@@ -26,12 +26,15 @@
 /* needed for SDL_IPHONE_MAX_GFORCE macro */
 #include "SDL_config_iphoneos.h"
 
+#include "SDL_assert.h"
 #include "SDL_events.h"
 #include "SDL_joystick.h"
 #include "SDL_hints.h"
 #include "SDL_stdinc.h"
 #include "../SDL_sysjoystick.h"
 #include "../SDL_joystick_c.h"
+#include "../steam/SDL_steamcontroller.h"
+
 
 #if !SDL_EVENTS_DISABLED
 #include "../../events/SDL_events_c.h"
@@ -242,7 +245,7 @@ SDL_SYS_RemoveJoystickDevice(SDL_JoystickDeviceItem *device)
 
     --numjoysticks;
 
-	SDL_PrivateJoystickRemoved(device->instance_id);
+    SDL_PrivateJoystickRemoved(device->instance_id);
 
     SDL_free(device->name);
     SDL_free(device);
@@ -266,6 +269,50 @@ SDL_AppleTVRemoteRotationHintChanged(void *udata, const char *name, const char *
 }
 #endif /* TARGET_OS_TV */
 
+static SDL_bool SteamControllerConnectedCallback(const char *name, SDL_JoystickGUID guid, int *device_instance)
+{
+    SDL_JoystickDeviceItem *device = (SDL_JoystickDeviceItem *)SDL_calloc(1, sizeof(SDL_JoystickDeviceItem));
+    if (device == NULL) {
+        return SDL_FALSE;
+    }
+
+    *device_instance = device->instance_id = instancecounter++;
+	device->name = SDL_strdup(name);
+	device->guid = guid;
+	SDL_GetSteamControllerInputs(&device->nbuttons,
+								 &device->naxes,
+								 &device->nhats);
+    device->m_bSteamController = SDL_TRUE;
+
+    if (deviceList == NULL) {
+        deviceList = device;
+    } else {
+        SDL_JoystickDeviceItem *lastdevice = deviceList;
+        while (lastdevice->next != NULL) {
+            lastdevice = lastdevice->next;
+        }
+        lastdevice->next = device;
+    }
+
+    ++numjoysticks;
+
+    SDL_PrivateJoystickAdded(numjoysticks - 1);
+
+    return SDL_TRUE;
+}
+
+static void SteamControllerDisconnectedCallback(int device_instance)
+{
+    SDL_JoystickDeviceItem *item;
+
+	for (item = deviceList; item; item = item->next) {
+        if (item->instance_id == device_instance) {
+			SDL_SYS_RemoveJoystickDevice(item);
+			break;
+        }
+    }
+}
+
 /* Function to scan the system for joysticks.
  * Joystick 0 should be the system default joystick.
  * It should return 0, or -1 on an unrecoverable fatal error.
@@ -276,6 +323,9 @@ SDL_SYS_JoystickInit(void)
     @autoreleasepool {
         NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
 
+        SDL_InitSteamControllers(SteamControllerConnectedCallback,
+                                 SteamControllerDisconnectedCallback);
+
 #if !TARGET_OS_TV
         if (SDL_GetHintBoolean(SDL_HINT_ACCELEROMETER_AS_JOYSTICK, SDL_TRUE)) {
             /* Default behavior, accelerometer as joystick */
@@ -335,6 +385,7 @@ SDL_SYS_NumJoysticks(void)
 void
 SDL_SYS_JoystickDetect(void)
 {
+    SDL_UpdateSteamControllers();
 }
 
 /* Function to get the device-dependent name of a joystick */
@@ -628,6 +679,11 @@ SDL_SYS_JoystickUpdate(SDL_Joystick * joystick)
     if (device == NULL) {
         return;
     }
+    
+    if (device->m_bSteamController) {
+        SDL_UpdateSteamController(joystick);
+        return;
+    }
 
     if (device->accelerometer) {
         SDL_SYS_AccelerometerUpdate(joystick);
@@ -696,6 +752,8 @@ SDL_SYS_JoystickQuit(void)
 #endif /* !TARGET_OS_TV */
     }
 
+    SDL_QuitSteamControllers();
+
     numjoysticks = 0;
 }
 

+ 3 - 0
src/joystick/iphoneos/SDL_sysjoystick_c.h

@@ -44,6 +44,9 @@ typedef struct joystick_hwdata
     int nbuttons;
     int nhats;
 
+    /* Steam Controller support */
+    SDL_bool m_bSteamController;
+
     struct joystick_hwdata *next;
 } joystick_hwdata;
 

+ 122 - 26
src/joystick/linux/SDL_sysjoystick.c

@@ -38,8 +38,10 @@
 #include "SDL_assert.h"
 #include "SDL_joystick.h"
 #include "SDL_endian.h"
+#include "../../events/SDL_events_c.h"
 #include "../SDL_sysjoystick.h"
 #include "../SDL_joystick_c.h"
+#include "../steam/SDL_steamcontroller.h"
 #include "SDL_sysjoystick_c.h"
 
 /* This isn't defined in older Linux kernel headers */
@@ -66,6 +68,9 @@ typedef struct SDL_joylist_item
     dev_t devnum;
     struct joystick_hwdata *hwdata;
     struct SDL_joylist_item *next;
+
+    /* Steam Controller support */
+    SDL_bool m_bSteamController;
 } SDL_joylist_item;
 
 static SDL_joylist_item *SDL_joylist = NULL;
@@ -73,6 +78,7 @@ static SDL_joylist_item *SDL_joylist_tail = NULL;
 static int numjoysticks = 0;
 static int instance_counter = 0;
 
+
 #define test_bit(nr, addr) \
     (((1UL << ((nr) % (sizeof(long) * 8))) & ((addr)[(nr) / (sizeof(long) * 8)])) != 0)
 #define NBITS(x) ((((x)-1)/(sizeof(long) * 8))+1)
@@ -428,6 +434,77 @@ JoystickInitWithUdev(void)
 }
 #endif
 
+static SDL_bool SteamControllerConnectedCallback(const char *name, SDL_JoystickGUID guid, int *device_instance)
+{
+    SDL_joylist_item *item;
+
+    item = (SDL_joylist_item *) SDL_calloc(1, sizeof (SDL_joylist_item));
+    if (item == NULL) {
+        return SDL_FALSE;
+    }
+
+    item->path = SDL_strdup("");
+    item->name = SDL_strdup(name);
+    item->guid = guid;
+    item->m_bSteamController = SDL_TRUE;
+
+    if ((item->path == NULL) || (item->name == NULL)) {
+         SDL_free(item->path);
+         SDL_free(item->name);
+         SDL_free(item);
+         return SDL_FALSE;
+    }
+
+    *device_instance = item->device_instance = instance_counter++;
+    if (SDL_joylist_tail == NULL) {
+        SDL_joylist = SDL_joylist_tail = item;
+    } else {
+        SDL_joylist_tail->next = item;
+        SDL_joylist_tail = item;
+    }
+
+    /* Need to increment the joystick count before we post the event */
+    ++numjoysticks;
+
+    SDL_PrivateJoystickAdded(numjoysticks - 1);
+
+    return SDL_TRUE;
+}
+
+static void SteamControllerDisconnectedCallback(int device_instance)
+{
+    SDL_joylist_item *item;
+    SDL_joylist_item *prev = NULL;
+
+    for (item = SDL_joylist; item != NULL; item = item->next) {
+        /* found it, remove it. */
+        if (item->device_instance == device_instance) {
+            if (item->hwdata) {
+                item->hwdata->item = NULL;
+            }
+            if (prev != NULL) {
+                prev->next = item->next;
+            } else {
+                SDL_assert(SDL_joylist == item);
+                SDL_joylist = item->next;
+            }
+            if (item == SDL_joylist_tail) {
+                SDL_joylist_tail = prev;
+            }
+
+            /* Need to decrement the joystick count before we post the event */
+            --numjoysticks;
+
+            SDL_PrivateJoystickRemoved(item->device_instance);
+
+            SDL_free(item->name);
+            SDL_free(item);
+            return;
+        }
+        prev = item;
+    }
+}
+
 int
 SDL_SYS_JoystickInit(void)
 {
@@ -447,6 +524,9 @@ SDL_SYS_JoystickInit(void)
         SDL_free(envcopy);
     }
 
+    SDL_InitSteamControllers(SteamControllerConnectedCallback,
+                             SteamControllerDisconnectedCallback);
+
 #if SDL_USE_LIBUDEV
     return JoystickInitWithUdev();
 #else 
@@ -466,7 +546,8 @@ SDL_SYS_JoystickDetect(void)
 #if SDL_USE_LIBUDEV
     SDL_UDEV_Poll();
 #endif
-    
+
+    SDL_UpdateSteamControllers();
 }
 
 static SDL_joylist_item *
@@ -650,47 +731,53 @@ int
 SDL_SYS_JoystickOpen(SDL_Joystick * joystick, int device_index)
 {
     SDL_joylist_item *item = JoystickByDevIndex(device_index);
-    char *fname = NULL;
-    int fd = -1;
 
     if (item == NULL) {
         return SDL_SetError("No such device");
     }
 
-    fname = item->path;
-    fd = open(fname, O_RDONLY, 0);
-    if (fd < 0) {
-        return SDL_SetError("Unable to open %s", fname);
-    }
-
     joystick->instance_id = item->device_instance;
     joystick->hwdata = (struct joystick_hwdata *)
-        SDL_malloc(sizeof(*joystick->hwdata));
+        SDL_calloc(1, sizeof(*joystick->hwdata));
     if (joystick->hwdata == NULL) {
-        close(fd);
         return SDL_OutOfMemory();
     }
-    SDL_memset(joystick->hwdata, 0, sizeof(*joystick->hwdata));
     joystick->hwdata->item = item;
     joystick->hwdata->guid = item->guid;
-    joystick->hwdata->fd = fd;
-    joystick->hwdata->fname = SDL_strdup(item->path);
-    if (joystick->hwdata->fname == NULL) {
-        SDL_free(joystick->hwdata);
-        joystick->hwdata = NULL;
-        close(fd);
-        return SDL_OutOfMemory();
+    joystick->hwdata->m_bSteamController = item->m_bSteamController;
+
+    if (item->m_bSteamController) {
+        joystick->hwdata->fd = -1;
+        SDL_GetSteamControllerInputs(&joystick->nbuttons,
+                                     &joystick->naxes,
+                                     &joystick->nhats);
+    } else {
+        int fd = open(item->path, O_RDONLY, 0);
+        if (fd < 0) {
+            SDL_free(joystick->hwdata);
+            joystick->hwdata = NULL;
+            return SDL_SetError("Unable to open %s", item->path);
+        }
+
+        joystick->hwdata->fd = fd;
+        joystick->hwdata->fname = SDL_strdup(item->path);
+        if (joystick->hwdata->fname == NULL) {
+            SDL_free(joystick->hwdata);
+            joystick->hwdata = NULL;
+            close(fd);
+            return SDL_OutOfMemory();
+        }
+
+        /* Set the joystick to non-blocking read mode */
+        fcntl(fd, F_SETFL, O_NONBLOCK);
+
+        /* Get the number of buttons and axes on the joystick */
+        ConfigJoystick(joystick, fd);
     }
 
     SDL_assert(item->hwdata == NULL);
     item->hwdata = joystick->hwdata;
 
-    /* Set the joystick to non-blocking read mode */
-    fcntl(fd, F_SETFL, O_NONBLOCK);
-
-    /* Get the number of buttons and axes on the joystick */
-    ConfigJoystick(joystick, fd);
-
     /* mark joystick as fresh and ready */
     joystick->hwdata->fresh = 1;
 
@@ -881,6 +968,11 @@ SDL_SYS_JoystickUpdate(SDL_Joystick * joystick)
 {
     int i;
 
+    if (joystick->hwdata->m_bSteamController) {
+        SDL_UpdateSteamController(joystick);
+        return;
+    }
+
     HandleInputEvents(joystick);
 
     /* Deliver ball motion updates */
@@ -902,7 +994,9 @@ void
 SDL_SYS_JoystickClose(SDL_Joystick * joystick)
 {
     if (joystick->hwdata) {
-        close(joystick->hwdata->fd);
+        if (joystick->hwdata->fd >= 0) {
+            close(joystick->hwdata->fd);
+        }
         if (joystick->hwdata->item) {
             joystick->hwdata->item->hwdata = NULL;
         }
@@ -936,6 +1030,8 @@ SDL_SYS_JoystickQuit(void)
     SDL_UDEV_DelCallback(joystick_udev_callback);
     SDL_UDEV_Quit();
 #endif
+
+    SDL_QuitSteamControllers();
 }
 
 SDL_JoystickGUID SDL_SYS_JoystickGetDeviceGUID( int device_index )

+ 3 - 0
src/joystick/linux/SDL_sysjoystick_c.h

@@ -52,6 +52,9 @@ struct joystick_hwdata
     } abs_correct[ABS_MAX];
 
     int fresh;
+
+    /* Steam Controller support */
+    SDL_bool m_bSteamController;
 };
 
 /* vi: set ts=4 sw=4 expandtab: */

+ 52 - 0
src/joystick/steam/SDL_steamcontroller.c

@@ -0,0 +1,52 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2017 Sam Lantinga <slouken@libsdl.org>
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#include "../SDL_sysjoystick.h"
+#include "../SDL_joystick_c.h"
+#include "SDL_steamcontroller.h"
+
+
+void SDL_InitSteamControllers(SteamControllerConnectedCallback_t connectedCallback,
+                              SteamControllerDisconnectedCallback_t disconnectedCallback)
+{
+}
+
+void SDL_GetSteamControllerInputs(int *nbuttons, int *naxes, int *nhats)
+{
+    *nbuttons = 0;
+    *naxes = 0;
+    *nhats = 0;
+}
+
+void SDL_UpdateSteamControllers()
+{
+}
+
+void SDL_UpdateSteamController(SDL_Joystick *joystick)
+{
+}
+
+void SDL_QuitSteamControllers()
+{
+}
+
+/* vi: set ts=4 sw=4 expandtab: */