Skip to content

Instantly share code, notes, and snippets.

@osnr
Created November 25, 2020 02:24
Show Gist options
  • Save osnr/3b8bd2c4a278bf554dc009da21362c14 to your computer and use it in GitHub Desktop.
Save osnr/3b8bd2c4a278bf554dc009da21362c14 to your computer and use it in GitHub Desktop.
-- based on https://www.reddit.com/r/gamedev/comments/jumvi5/dualsense_haptics_leds_and_more_hid_output_report/gcemle4/
-- requires hidapi + run with LuaJIT
local ffi = require('ffi')
ffi.cdef[[
typedef struct hid_device_ hid_device; /**< opaque hidapi structure */
int hid_init(void);
hid_device * hid_open(unsigned short vendor_id, unsigned short product_id, const wchar_t *serial_number);
int hid_get_manufacturer_string(hid_device *dev, wchar_t *string, size_t maxlen);
int hid_get_product_string(hid_device *dev, wchar_t *string, size_t maxlen);
int hid_read(hid_device *dev, unsigned char *data, size_t length);
int hid_write(hid_device *dev, const unsigned char *data, size_t length);
]]
local hidapi = ffi.load('hidapi')
local res = hidapi.hid_init()
if handle then return nil end
handle = hidapi.hid_open(0x054c, 0x0ce6, nil)
ffi.cdef[[ size_t wcstombs (char* dest, const wchar_t* src, size_t max); ]]
function wprint(prefix, ws)
local s = ffi.new('char[255]', 1)
ffi.C.wcstombs(s, ws, 255)
print(prefix, ffi.string(s))
end
local wstr = ffi.new('wchar_t[255]', 1)
hidapi.hid_get_manufacturer_string(handle, wstr, 255)
wprint('Manufacturer String:', wstr) -- Sony Interactive Entertainment
hidapi.hid_get_product_string(handle, wstr, 255)
wprint('Product String:', wstr) -- Wireless Controller
local output_report = ffi.new('char[48]')
local data = ffi.new('char[64]')
local fun = 0
local player = 1
while true do
hidapi.hid_read(handle, data, 64) -- get input report
fun = fun + 1
if fun == 256 then fun = 0 player = (player + 1) % 0x20 end
output_report[0] = 0x02
-- allow us to set everything (not necessarily the best idea, but can be good for testing)
output_report[1] = 0xff
output_report[2] = 0xff-8
-- briefly alternate the main motors with gaps inbetween
output_report[3] = (fun > 128 and fun < 192 and 255) or 0
output_report[4] = (fun < 64 and 255) or 0
-- pulsating Mic LED
output_report[9] = 0x02
-- right trigger motor at linear resistance starting part of the way
output_report[11] = 1
output_report[12] = 0x5f
output_report[13] = 0xff
-- left trigger with similar effect as the PS5 demo
if fun % 32 < 16 then output_report[22] = 0 else output_report[22] = 2 end
output_report[23] = 0x00
output_report[24] = 0xff
output_report[25] = 0xff
-- cycling LEDs
output_report[44] = player
output_report[45] = fun
output_report[47] = fun+128
hidapi.hid_write(handle, output_report, 48)
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment