Steam Deck input (SOLVED)

I finally have a Steam Deck!

The issue with raw gamepad input was that gui scripts don’t receive it, but regular scripts do. Armed with this knowledge, I recreated a utility similar to what @britzl mentioned. This is me partially mapping my old Xbox controller:

Regrettably, I just don’t seem to get any input from the Steam Deck - other than an unexpected gamepad name:

For reference, this is the script I use to gather mappings. Might be useful for other situations:


--pre-hash
local GAMEPAD_LSTICK_LEFT = hash("gamepad_lstick_left")
local GAMEPAD_LSTICK_RIGHT = hash("gamepad_lstick_right")
local GAMEPAD_LSTICK_DOWN = hash("gamepad_lstick_down")
local GAMEPAD_LSTICK_UP = hash("gamepad_lstick_up")
local GAMEPAD_LSTICK_CLICK = hash("gamepad_lstick_click")
local GAMEPAD_LTRIGGER = hash("gamepad_ltrigger")
local GAMEPAD_LSHOULDER = hash("gamepad_lshoulder")
local GAMEPAD_LPAD_LEFT = hash("gamepad_lpad_left")
local GAMEPAD_LPAD_RIGHT = hash("gamepad_lpad_right")
local GAMEPAD_LPAD_DOWN = hash("gamepad_lpad_down")
local GAMEPAD_LPAD_UP = hash("gamepad_lpad_up")
local GAMEPAD_RSTICK_LEFT = hash("gamepad_rstick_left")
local GAMEPAD_RSTICK_RIGHT = hash("gamepad_rstick_right")
local GAMEPAD_RSTICK_DOWN = hash("gamepad_rstick_down")
local GAMEPAD_RSTICK_UP = hash("gamepad_rstick_up")
local GAMEPAD_RSTICK_CLICK = hash("gamepad_rstick_click")
local GAMEPAD_RTRIGGER = hash("gamepad_rtrigger")
local GAMEPAD_RSHOULDER = hash("gamepad_rshoulder")
local GAMEPAD_RPAD_LEFT = hash("gamepad_rpad_left")
local GAMEPAD_RPAD_RIGHT = hash("gamepad_rpad_right")
local GAMEPAD_RPAD_DOWN = hash("gamepad_rpad_down")
local GAMEPAD_RPAD_UP = hash("gamepad_rpad_up")
local GAMEPAD_START = hash("gamepad_start")
local GAMEPAD_BACK = hash("gamepad_back")
local GAMEPAD_GUIDE = hash("gamepad_guide")

local hash_to_text = {
	[GAMEPAD_LSTICK_LEFT] = "GAMEPAD_LSTICK_LEFT",
	[GAMEPAD_LSTICK_RIGHT] = "GAMEPAD_LSTICK_RIGHT",
	[GAMEPAD_LSTICK_DOWN] = "GAMEPAD_LSTICK_DOWN",
	[GAMEPAD_LSTICK_UP] = "GAMEPAD_LSTICK_UP",
	[GAMEPAD_LSTICK_CLICK] = "GAMEPAD_LSTICK_CLICK",
	[GAMEPAD_LTRIGGER] = "GAMEPAD_LTRIGGER",
	[GAMEPAD_LSHOULDER] = "GAMEPAD_LSHOULDER",
	[GAMEPAD_LPAD_LEFT] = "GAMEPAD_LPAD_LEFT",
	[GAMEPAD_LPAD_RIGHT] = "GAMEPAD_LPAD_RIGHT",
	[GAMEPAD_LPAD_DOWN] = "GAMEPAD_LPAD_DOWN",
	[GAMEPAD_LPAD_UP] = "GAMEPAD_LPAD_UP",
	[GAMEPAD_RSTICK_LEFT] = "GAMEPAD_RSTICK_LEFT",
	[GAMEPAD_RSTICK_RIGHT] = "GAMEPAD_RSTICK_RIGHT",
	[GAMEPAD_RSTICK_DOWN] = "GAMEPAD_RSTICK_DOWN",
	[GAMEPAD_RSTICK_UP] = "GAMEPAD_RSTICK_UP",
	[GAMEPAD_RSTICK_CLICK] = "GAMEPAD_RSTICK_CLICK",
	[GAMEPAD_RTRIGGER] = "GAMEPAD_RTRIGGER",
	[GAMEPAD_RSHOULDER] = "GAMEPAD_RSHOULDER",
	[GAMEPAD_RPAD_LEFT] = "GAMEPAD_RPAD_LEFT",
	[GAMEPAD_RPAD_RIGHT] = "GAMEPAD_RPAD_RIGHT",
	[GAMEPAD_RPAD_DOWN] = "GAMEPAD_RPAD_DOWN",
	[GAMEPAD_RPAD_UP] = "GAMEPAD_RPAD_UP",
	[GAMEPAD_START] = "GAMEPAD_START",
	[GAMEPAD_BACK] = "GAMEPAD_BACK",
	[GAMEPAD_GUIDE] = "GAMEPAD_GUIDE",
}

function init(self)
	msg.post(".", "acquire_input_focus")

	self.data = {}
	self.formatted_data = {}
end

function update(self, dt)
	
	if self.gamepad_name then
		label.set_text("#gamepad_name", "Gamepad name: " .. self.gamepad_name)
	else
		label.set_text("#gamepad_name", "No gamepad detected.")
	end

	local txt = ""
	for name, data in pairs(self.data) do
		
		txt = txt .. name .. " type: " .. data.type .. " index: " .. data.index .. "\n"
	end
	label.set_text("#mapping", txt)

	self.formatted_data = {}
	for name, data in pairs(self.data) do
		if data.type == "GAMEPAD_TYPE_HAT" then
			table.insert(self.formatted_data, "map { input: " .. name .. " type: " .. data.type .. " index: 0 hat_mask: " .. data.index .. " }")
		elseif data.type == "GAMEPAD_TYPE_AXIS" then
			--this needs "mod" details, do manually
			table.insert(self.formatted_data, "map { input: " .. name .. " type: " .. data.type .. " index: " .. data.index .. " }")
		else
			table.insert(self.formatted_data, "map { input: " .. name .. " type: " .. data.type .. " index: " .. data.index .. " }")
		end
	end
	pprint(self.formatted_data)
end

function on_input(self, action_id, action)
	
	if action_id == hash("gamepad_connected") then
		self.gamepad_name = action.gamepad_name
	end

	if action_id == hash("gamepad_raw") then
		self.previous_raw = action
	else
		if action.pressed then

			if not self.previous_raw then
				return
			end

			--is it a button?
			for i, state in pairs(self.previous_raw.gamepad_buttons) do
				if state == 1 then
					self.data[hash_to_text[action_id]] = {type = "GAMEPAD_TYPE_BUTTON", index = i}
					break
				end
			end

			--is it an axis?
			local largest_state = 0
			local largest_i = nil
			for i, state in pairs(self.previous_raw.gamepad_axis) do
				state = math.abs(state)
				if state > 0.5 then
					if state > largest_state then
						largest_state = state
						largest_i = i
					end
				end
			end
			if largest_i then
				self.data[hash_to_text[action_id]] = {type = "GAMEPAD_TYPE_AXIS", index = largest_i}
			end

			--is it a hat?
			for i, state in pairs(self.previous_raw.gamepad_hats) do
				if state == 1 then
					self.data[hash_to_text[action_id]] = {type = "GAMEPAD_TYPE_HAT", index = i}
					break
				end
			end
		end
	end
end

I think the axis detection needs some work because I use math.abs() when I actually think there are supposed to be negative values.

I’m at a loss as to how to move forward at this point!

2 Likes

Yep, that’s an oversight on our part. I’ll see about fixing that soon!

Ok, but you do get a gamepad connected event and that name?

I think next step would be to prepare a version of Defold with some additional to try and pinpoint where it goes wrong with joystick/gamepad detection.

1 Like

Yes, I do get a gamepad_connected event with that name.

What additional things would you try?

I don’t know really. We use Xinput on Linux, but it could be that we need to look more closely at the implementation and how the Steam Deck works.

1 Like

OK. Perhaps something to look at when you get your Deck. I’ve managed to get Void Scrappers to work by emulating mouse + keyboard, so for me personally it’s just Fates of Ort that doesn’t work.

1 Like

Ok, so I was a dummy! My script would only ever catch mapped input so no surprise it wasn’t displaying anything.

I’ve fixed that now and actually got some input! I mapped it and tried again.

The keys in my mapping don’t match up at all, it seems. I thought that perhaps the generic sounding name (“Microsoft X-Box 360 pad 0”) might be clashing with other similarly named mappings, so I tried a build with just mine. Still doesn’t match. Why might that be?!

Here's my mapping
driver
{
    device: "Microsoft X-Box 360 pad 0"
    platform: "linux"
    dead_zone: 0.2
    map { input: GAMEPAD_LSTICK_LEFT type: GAMEPAD_TYPE_AXIS index: 1 mod { mod: GAMEPAD_MODIFIER_NEGATE } mod { mod: GAMEPAD_MODIFIER_CLAMP } }
    map { input: GAMEPAD_LSTICK_RIGHT type: GAMEPAD_TYPE_AXIS index: 1 mod { mod: GAMEPAD_MODIFIER_CLAMP } }
    map { input: GAMEPAD_LSTICK_DOWN type: GAMEPAD_TYPE_AXIS index: 2 mod { mod: GAMEPAD_MODIFIER_NEGATE } mod { mod: GAMEPAD_MODIFIER_CLAMP } }
    map { input: GAMEPAD_LSTICK_UP type: GAMEPAD_TYPE_AXIS index: 2 mod { mod: GAMEPAD_MODIFIER_CLAMP } }
    map { input: GAMEPAD_LSTICK_CLICK type: GAMEPAD_TYPE_BUTTON index: 10 }
    map { input: GAMEPAD_LTRIGGER type: GAMEPAD_TYPE_AXIS index: 3 mod { mod: GAMEPAD_MODIFIER_SCALE } }
    map { input: GAMEPAD_LSHOULDER type: GAMEPAD_TYPE_BUTTON index: 5 }
    map { input: GAMEPAD_LPAD_LEFT type: GAMEPAD_TYPE_AXIS index: 7 mod { mod: GAMEPAD_MODIFIER_NEGATE } mod { mod: GAMEPAD_MODIFIER_CLAMP } }
    map { input: GAMEPAD_LPAD_RIGHT type: GAMEPAD_TYPE_AXIS index: 7 mod { mod: GAMEPAD_MODIFIER_CLAMP } }
    map { input: GAMEPAD_LPAD_DOWN type: GAMEPAD_TYPE_AXIS index: 8 mod { mod: GAMEPAD_MODIFIER_NEGATE } mod { mod: GAMEPAD_MODIFIER_CLAMP } }
    map { input: GAMEPAD_LPAD_UP type: GAMEPAD_TYPE_AXIS index: 8 mod { mod: GAMEPAD_MODIFIER_CLAMP } }
    map { input: GAMEPAD_RSTICK_LEFT type: GAMEPAD_TYPE_AXIS index: 4 mod { mod: GAMEPAD_MODIFIER_CLAMP } }
    map { input: GAMEPAD_RSTICK_RIGHT type: GAMEPAD_TYPE_AXIS index: 4 mod { mod: GAMEPAD_MODIFIER_NEGATE } mod { mod: GAMEPAD_MODIFIER_CLAMP } }
    map { input: GAMEPAD_RSTICK_DOWN type: GAMEPAD_TYPE_AXIS index: 5 mod { mod: GAMEPAD_MODIFIER_CLAMP } }
    map { input: GAMEPAD_RSTICK_UP type: GAMEPAD_TYPE_AXIS index: 5 mod { mod: GAMEPAD_MODIFIER_NEGATE } mod { mod: GAMEPAD_MODIFIER_CLAMP } }
    map { input: GAMEPAD_RSTICK_CLICK type: GAMEPAD_TYPE_BUTTON index: 11 }
    map { input: GAMEPAD_RTRIGGER type: GAMEPAD_TYPE_AXIS index: 6 mod { mod: GAMEPAD_MODIFIER_NEGATE } mod { mod: GAMEPAD_MODIFIER_SCALE } }
    map { input: GAMEPAD_RSHOULDER type: GAMEPAD_TYPE_BUTTON index: 6 }
    map { input: GAMEPAD_RPAD_LEFT type: GAMEPAD_TYPE_BUTTON index: 3 }
    map { input: GAMEPAD_RPAD_RIGHT type: GAMEPAD_TYPE_BUTTON index: 2 }
    map { input: GAMEPAD_RPAD_DOWN type: GAMEPAD_TYPE_BUTTON index: 1 }
    map { input: GAMEPAD_RPAD_UP type: GAMEPAD_TYPE_BUTTON index: 4 }
    map { input: GAMEPAD_START type: GAMEPAD_TYPE_BUTTON index: 8 }
    map { input: GAMEPAD_BACK type: GAMEPAD_TYPE_BUTTON index: 7 }
}
1 Like

Happy to hear that you made progress and could read out the raw input!

It’s strange that you do not get a match with your new gamepad binding…

Try without the trailing zero in the name, I think the engine postfixes the gamepad index to the name but looks for the mapping without the index. Don’t know if it’s the issue you’re having without having access to a steamdeck but you might as well try this:

“Microsoft X-Box 360 pad”

2 Likes

Interesting idea! Unfortunately it didn’t work - when I remove the trailing 0 I’m back to only raw input.

With the trailing 0, I do get mapped input, but it’s all jumbled. Did you think the trailing zero could have that effect?

What do you mean with jumbled? :face_with_monocle:

I get mapped input, but it’s incomplete and in the wrong position. E.g. the left trigger might display as rpad down, and rpad left might not be detected at all.

My app would show e.g. for rpad down that it was a button of index 1. That’s what I put in my mapping:

map { input: GAMEPAD_RPAD_DOWN type: GAMEPAD_TYPE_BUTTON index: 1 }

But then when I use the same data to match an action_id I get nothing or the wrong result. And this is for a .gamepads file with only the new mapping.

The screenshot with the different axis and index look strange.

You have LPAD_RIGHT, LPAD_LEFT, LSHOULDER and many others with type AXIS using the same index (3). Surely that can’t be right?

You’re right, that’s a bit wonky and long story short I’ve simplified my script to make it less likely I’m confusing things.

I’m quite confident in this screenshot.

What’s happening here is that the two triggers are continuously firing on axis 3 and 6. My mappings for these are:

map { input: GAMEPAD_LTRIGGER type: GAMEPAD_TYPE_AXIS index: 3 mod { mod: GAMEPAD_MODIFIER_SCALE } }
map { input: GAMEPAD_RTRIGGER type: GAMEPAD_TYPE_AXIS index: 6 mod { mod: GAMEPAD_MODIFIER_NEGATE } mod { mod: GAMEPAD_MODIFIER_SCALE } }

However they output as GAMEPAD_LSTICK_DOWN and GAMEPAD_RSTICK_DOWN.

I was also holding down RPAD_LEFT (not when I took the picture though, but the output mapping is stored). This is showing button index 3 in my raw output on the screenshot. The mapping for RPAD_LEFT:

map { input: GAMEPAD_RPAD_LEFT type: GAMEPAD_TYPE_BUTTON index: 3 }

What’s actually showing instead is GAMEPAD_RPAD_RIGHT, which is mapped as:

map { input: GAMEPAD_RPAD_RIGHT type: GAMEPAD_TYPE_BUTTON index: 2 }
My input capture script

--pre-hash
local GAMEPAD_LSTICK_LEFT = hash("gamepad_lstick_left")
local GAMEPAD_LSTICK_RIGHT = hash("gamepad_lstick_right")
local GAMEPAD_LSTICK_DOWN = hash("gamepad_lstick_down")
local GAMEPAD_LSTICK_UP = hash("gamepad_lstick_up")
local GAMEPAD_LSTICK_CLICK = hash("gamepad_lstick_click")
local GAMEPAD_LTRIGGER = hash("gamepad_ltrigger")
local GAMEPAD_LSHOULDER = hash("gamepad_lshoulder")
local GAMEPAD_LPAD_LEFT = hash("gamepad_lpad_left")
local GAMEPAD_LPAD_RIGHT = hash("gamepad_lpad_right")
local GAMEPAD_LPAD_DOWN = hash("gamepad_lpad_down")
local GAMEPAD_LPAD_UP = hash("gamepad_lpad_up")
local GAMEPAD_RSTICK_LEFT = hash("gamepad_rstick_left")
local GAMEPAD_RSTICK_RIGHT = hash("gamepad_rstick_right")
local GAMEPAD_RSTICK_DOWN = hash("gamepad_rstick_down")
local GAMEPAD_RSTICK_UP = hash("gamepad_rstick_up")
local GAMEPAD_RSTICK_CLICK = hash("gamepad_rstick_click")
local GAMEPAD_RTRIGGER = hash("gamepad_rtrigger")
local GAMEPAD_RSHOULDER = hash("gamepad_rshoulder")
local GAMEPAD_RPAD_LEFT = hash("gamepad_rpad_left")
local GAMEPAD_RPAD_RIGHT = hash("gamepad_rpad_right")
local GAMEPAD_RPAD_DOWN = hash("gamepad_rpad_down")
local GAMEPAD_RPAD_UP = hash("gamepad_rpad_up")
local GAMEPAD_START = hash("gamepad_start")
local GAMEPAD_BACK = hash("gamepad_back")
local GAMEPAD_GUIDE = hash("gamepad_guide")

local hash_to_text = {
	[GAMEPAD_LSTICK_LEFT] = "GAMEPAD_LSTICK_LEFT",
	[GAMEPAD_LSTICK_RIGHT] = "GAMEPAD_LSTICK_RIGHT",
	[GAMEPAD_LSTICK_DOWN] = "GAMEPAD_LSTICK_DOWN",
	[GAMEPAD_LSTICK_UP] = "GAMEPAD_LSTICK_UP",
	[GAMEPAD_LSTICK_CLICK] = "GAMEPAD_LSTICK_CLICK",
	[GAMEPAD_LTRIGGER] = "GAMEPAD_LTRIGGER",
	[GAMEPAD_LSHOULDER] = "GAMEPAD_LSHOULDER",
	[GAMEPAD_LPAD_LEFT] = "GAMEPAD_LPAD_LEFT",
	[GAMEPAD_LPAD_RIGHT] = "GAMEPAD_LPAD_RIGHT",
	[GAMEPAD_LPAD_DOWN] = "GAMEPAD_LPAD_DOWN",
	[GAMEPAD_LPAD_UP] = "GAMEPAD_LPAD_UP",
	[GAMEPAD_RSTICK_LEFT] = "GAMEPAD_RSTICK_LEFT",
	[GAMEPAD_RSTICK_RIGHT] = "GAMEPAD_RSTICK_RIGHT",
	[GAMEPAD_RSTICK_DOWN] = "GAMEPAD_RSTICK_DOWN",
	[GAMEPAD_RSTICK_UP] = "GAMEPAD_RSTICK_UP",
	[GAMEPAD_RSTICK_CLICK] = "GAMEPAD_RSTICK_CLICK",
	[GAMEPAD_RTRIGGER] = "GAMEPAD_RTRIGGER",
	[GAMEPAD_RSHOULDER] = "GAMEPAD_RSHOULDER",
	[GAMEPAD_RPAD_LEFT] = "GAMEPAD_RPAD_LEFT",
	[GAMEPAD_RPAD_RIGHT] = "GAMEPAD_RPAD_RIGHT",
	[GAMEPAD_RPAD_DOWN] = "GAMEPAD_RPAD_DOWN",
	[GAMEPAD_RPAD_UP] = "GAMEPAD_RPAD_UP",
	[GAMEPAD_START] = "GAMEPAD_START",
	[GAMEPAD_BACK] = "GAMEPAD_BACK",
	[GAMEPAD_GUIDE] = "GAMEPAD_GUIDE",
}

function init(self)
	msg.post(".", "acquire_input_focus")

	self.mappings = {}
end

function update(self, dt)
	
	--display gamepad name
	if self.gamepad_name then
		label.set_text("#gamepad_name", "Gamepad name: " .. self.gamepad_name)
	else
		label.set_text("#gamepad_name", "No gamepad detected.")
	end

	--display raw input
	if self.previous_raw then
		local txt = ""
		for category, data in pairs(self.previous_raw) do
			if category == "gamepad_buttons" then
				for id, value in pairs(data) do
					if value ~= 0 then
						txt = txt .. "Button: " .. id .. "\n"
					end
				end
			end
			if category == "gamepad_hats" then
				for id, value in pairs(data) do
					if value ~= 0 then
						txt = txt .. "Hat: " .. id .. "\n"
					end
				end
			end
			if category == "gamepad_axis" then
				for id, value in pairs(data) do
					if math.abs(value) > 0.5 then
						txt = txt .. "Axis: " .. id .. " Value: " .. math.ceil(value*100)/100 .. "\n"
					end
				end
			end
		end
		label.set_text("#unmapped", txt)
	end

	--display mapped input
	local txt = ""
	for name, _ in pairs(self.mappings) do
		txt = txt .. name .. "\n"
	end
	label.set_text("#mapping", txt)
end

function on_input(self, action_id, action)
	
	--capture gamepad name
	if action_id == hash("gamepad_connected") then
		self.gamepad_name = action.gamepad_name
	end


	if action_id == hash("gamepad_raw") then

		--capture raw data to display
		self.previous_raw = action

	elseif action_id then

		if action.pressed then

			--try to map action to a known action_id and convert it to text
			local name = hash_to_text[action_id]
			
			--store mapping to be displayed
			if name then
				self.mappings[name] = true
			end

		end
	end
end

My .gamepads file, with no other bindings included

driver
{
    device: "Microsoft X-Box 360 pad 0"
    platform: "linux"
    dead_zone: 0.2
    map { input: GAMEPAD_LSTICK_LEFT type: GAMEPAD_TYPE_AXIS index: 1 mod { mod: GAMEPAD_MODIFIER_NEGATE } mod { mod: GAMEPAD_MODIFIER_CLAMP } }
    map { input: GAMEPAD_LSTICK_RIGHT type: GAMEPAD_TYPE_AXIS index: 1 mod { mod: GAMEPAD_MODIFIER_CLAMP } }
    map { input: GAMEPAD_LSTICK_DOWN type: GAMEPAD_TYPE_AXIS index: 2 mod { mod: GAMEPAD_MODIFIER_NEGATE } mod { mod: GAMEPAD_MODIFIER_CLAMP } }
    map { input: GAMEPAD_LSTICK_UP type: GAMEPAD_TYPE_AXIS index: 2 mod { mod: GAMEPAD_MODIFIER_CLAMP } }
    map { input: GAMEPAD_LSTICK_CLICK type: GAMEPAD_TYPE_BUTTON index: 10 }
    map { input: GAMEPAD_LTRIGGER type: GAMEPAD_TYPE_AXIS index: 3 mod { mod: GAMEPAD_MODIFIER_SCALE } }
    map { input: GAMEPAD_LSHOULDER type: GAMEPAD_TYPE_BUTTON index: 5 }
    map { input: GAMEPAD_LPAD_LEFT type: GAMEPAD_TYPE_AXIS index: 7 mod { mod: GAMEPAD_MODIFIER_NEGATE } mod { mod: GAMEPAD_MODIFIER_CLAMP } }
    map { input: GAMEPAD_LPAD_RIGHT type: GAMEPAD_TYPE_AXIS index: 7 mod { mod: GAMEPAD_MODIFIER_CLAMP } }
    map { input: GAMEPAD_LPAD_DOWN type: GAMEPAD_TYPE_AXIS index: 8 mod { mod: GAMEPAD_MODIFIER_NEGATE } mod { mod: GAMEPAD_MODIFIER_CLAMP } }
    map { input: GAMEPAD_LPAD_UP type: GAMEPAD_TYPE_AXIS index: 8 mod { mod: GAMEPAD_MODIFIER_CLAMP } }
    map { input: GAMEPAD_RSTICK_LEFT type: GAMEPAD_TYPE_AXIS index: 4 mod { mod: GAMEPAD_MODIFIER_CLAMP } }
    map { input: GAMEPAD_RSTICK_RIGHT type: GAMEPAD_TYPE_AXIS index: 4 mod { mod: GAMEPAD_MODIFIER_NEGATE } mod { mod: GAMEPAD_MODIFIER_CLAMP } }
    map { input: GAMEPAD_RSTICK_DOWN type: GAMEPAD_TYPE_AXIS index: 5 mod { mod: GAMEPAD_MODIFIER_CLAMP } }
    map { input: GAMEPAD_RSTICK_UP type: GAMEPAD_TYPE_AXIS index: 5 mod { mod: GAMEPAD_MODIFIER_NEGATE } mod { mod: GAMEPAD_MODIFIER_CLAMP } }
    map { input: GAMEPAD_RSTICK_CLICK type: GAMEPAD_TYPE_BUTTON index: 11 }
    map { input: GAMEPAD_RTRIGGER type: GAMEPAD_TYPE_AXIS index: 6 mod { mod: GAMEPAD_MODIFIER_NEGATE } mod { mod: GAMEPAD_MODIFIER_SCALE } }
    map { input: GAMEPAD_RSHOULDER type: GAMEPAD_TYPE_BUTTON index: 6 }
    map { input: GAMEPAD_RPAD_LEFT type: GAMEPAD_TYPE_BUTTON index: 3 }
    map { input: GAMEPAD_RPAD_RIGHT type: GAMEPAD_TYPE_BUTTON index: 2 }
    map { input: GAMEPAD_RPAD_DOWN type: GAMEPAD_TYPE_BUTTON index: 1 }
    map { input: GAMEPAD_RPAD_UP type: GAMEPAD_TYPE_BUTTON index: 4 }
    map { input: GAMEPAD_START type: GAMEPAD_TYPE_BUTTON index: 8 }
    map { input: GAMEPAD_BACK type: GAMEPAD_TYPE_BUTTON index: 7 }
}

Ok, what kind of value are you seeing?

I don’t understand this. If the .gamepads file you created is anything to go by GAMEPAD_LSTICK_DOWN and GAMEPAD_RSTICK_DOWN are mapped to AXIS and index 2 and 5. How can they output to something else then?

Keep in mind that the raw input is giving you values for buttons, axis and hats in an order that is fixed for the controller. It is not guaranteed that all controllers have their buttons and sticks mapped to the same indices. This is why the .gamepad file mappings exist. To translate the raw values to a predefined set of buttons and axis such that the mapping of gamepad input in a game is controller agnostic.

What you see in the screenshot. If I don’t touch the triggers they constantly output -1 on axis 3 and 1 on axis 6. Do you mean something else? If I press the triggers, the values invert (1 and -1, respectively).

When I receive raw input, I store the entire action table in self.previous_raw. I then iterate over that entire table and display each value on the left of the screenshot.

Yes, I don’t understand this either!

Yes - I created this mapping myself by pushing each of the buttons on the Deck and noting down the button/axis/hat.

Either something very weird is going on, or I have made a fundamental mistake in my script.

What if you try your script with a gamepad that is known to work and where there are existing bindings you can compare with? Are you able to reproduce the gamepad binding from the raw input?

Good idea. I get exactly the same behaviour from my own Xbox controller that normally works. I guess user error? But I really have no idea what I’m doing wrong.

Ok, let me take a look later this evening.

Thank you. I imagine you’ll end up rolling your own, but here is my project for reference. I’m very curious to understand what I’m doing wrong.

SteamDeckInput.zip (6.2 KB)

Oh, I think I’ve found your problem. The .gamepads file is 0-indexed, although the raw inputs you get in Lua are 1-indexed (for easy iteration with ipairs). You need to subtract 1 from the values when you create your definitions in the .gamepads file.

3 Likes