ds4drv icon indicating copy to clipboard operation
ds4drv copied to clipboard

Rumble support

Open Ape opened this issue 8 years ago • 23 comments

We can send rumble events to the physical controller just fine, but we are not currently supporting rumble features in the evdev end so games cannot actually use rumble.

Ape avatar Jul 03 '16 14:07 Ape

Do you have any links explaining why evdev doesn't support rumble? Is there any way around this you've seen?

poconbhui avatar Jul 07 '16 21:07 poconbhui

Evdev itself would allow rumble (force feedback) support. See this for information about it. However, python-evdev doesn't seem to support rumble, or at least it didn't in the past. Here is an old pull request discussing that.

Ape avatar Jul 08 '16 17:07 Ape

Hi! This is my code for send vibration in gamepad in python (works with xbox 360 controller, dualshock 4, wii remote).

import fcntl, struct, array, time

EVIOCRMFF = 0x40044581
EVIOCSFF = 0x40304580
LOG_CLASS_ON = False
TIME_DELTA = 250

class Vibrate:

    def __init__(self, file):
        self.ff_joy = open(file, "r+")

    def close(self):
        self.ff_joy.close()

    def new_effect(self, strong, weak, length):
        effect = struct.pack('HhHHHHHxHH', 0x50, -1, 0, 0, 0, length, 0, int(strong * 0xFFFF), int(weak * 0xFFFF))
        a = array.array('h', effect)
        fcntl.ioctl(self.ff_joy, EVIOCSFF, a, True)
        return a[1]
        id = a[1]
        return (ev_play, ev_stop)

    def play_efect(self, id):
        if type(id) == tuple or type(id) == list:
            ev_play = ''
            for i in id:
                ev_play = ev_play + struct.pack('LLHHi', 0, 0, 0x15, i, 1)
        else:
            ev_play = struct.pack('LLHHi', 0, 0, 0x15, id, 1)
        self.ff_joy.write(ev_play)
        self.ff_joy.flush()

    def stop_effect(self, id):
        if type(id) == tuple or type(id) == list:
            ev_stop = ''
            for i in id:
                ev_stop = ev_stop + struct.pack('LLHHi', 0, 0, 0x15, i, 0)
        else:
            ev_stop = struct.pack('LLHHi', 0, 0, 0x15, id, 0)
        self.ff_joy.write(ev_stop)
        self.ff_joy.flush()

    def forget_effect(self, id):
        if type(id) == tuple or type(id) == list:
            for i in id:
                fcntl.ioctl(self.ff_joy, EVIOCRMFF, i)
        else:
            fcntl.ioctl(self.ff_joy, EVIOCRMFF, id)

f = Vibrate("/dev/input/event14")
p = f.new_effect(1.0, 1.0, TIME_DELTA )
f.play_efect((p))
time.sleep(TIME_DELTA / 1000.0)
f.stop_effect((p))
f.forget_effect((p))

kharlashkin avatar Oct 04 '16 02:10 kharlashkin

@kharlashkin Hi. Are you saying you are able to get rumble to work with this code? If so, what file is this that you have provided? I would like to add it to get rumble to work if possible. Thanks!

Millsionaire avatar Nov 20 '16 21:11 Millsionaire

@Millsionaire Hi! You must write only correct "/dev/input/event14" for testing this code. Sorry for my english.

kharlashkin avatar Nov 21 '16 06:11 kharlashkin

Hi,

for me the ds4drv correctly creates /dev/input/event0 (raspberry pi 3). However, fftest cannot play any rumble effects ("Error: function not implemented").

The code posted above does not work ("invalid argument").

How can I make the controller rumble? Any working c code/program is appreciated.

jrahlf avatar Dec 05 '16 16:12 jrahlf

Can't this be done through libinput?

logos88 avatar Feb 02 '17 21:02 logos88

@kharlashkin

with your code:

└───╼  ds4drv                                                                                                                                                                                                                                                                                                                 
[info][controller 1] Created devices /dev/input/js0 (joystick) /dev/input/event7 (evdev)                                                                                                                                                                                                                                      
[info][bluetooth] Scanning for devices                                                                                                                                                                                                                                                                                        
[info][bluetooth] Found device 00:01:6C:8D:29:C5                                                                                                                                                                                                                                                                              
[info][controller 1] Connected to Bluetooth Controller (00:01:6C:8D:29:C5)                                                                                                                                                                                                                                                    
[info][bluetooth] Scanning for devices                                                                                                                                                                                                                                                                                        
[info][controller 1] Battery: Fully charged  
└───╼  python rumble.py 
Traceback (most recent call last):
  File "rumble.py", line 51, in <module>
    f = Vibrate("/dev/input/event7")
  File "rumble.py", line 11, in __init__
    self.ff_joy = open(file, "r+")
io.UnsupportedOperation: File or stream is not seekable.

any hint?

is a DualShock 4 20th anniversary edition

sl1pkn07 avatar May 11 '17 21:05 sl1pkn07

In first you must find your gamepad in "/dev/input/eventXX" and insert true event. For testing vibration in terminal try: fftest /dev/input/eventXX

kharlashkin avatar May 12 '17 04:05 kharlashkin

I think autofind true event try make with glob.glob('/dev/input/event[A-Za-z]*'). Sorry for my english.

kharlashkin avatar May 12 '17 04:05 kharlashkin

you mean like this?

[1036906.183060] input: Sony Computer Entertainment Wireless Controller as /devices/virtual/input/input119

from dmesg

note: using python-evdev 0.6.4

sl1pkn07 avatar May 12 '17 04:05 sl1pkn07

I don't have any dualshock for testing, but I'm sure - when dualshock 4 connect with cable to PC - its has vibrate from fftest /dev/input/eventXX. One of my friend test this.

kharlashkin avatar May 12 '17 05:05 kharlashkin

then only works with USB? not working through BT?

sl1pkn07 avatar May 14 '17 13:05 sl1pkn07

On occasion, I will ask him about BT.

kharlashkin avatar May 14 '17 16:05 kharlashkin

other question, what version of python-evdev is used? ff branch?

sl1pkn07 avatar May 14 '17 17:05 sl1pkn07

On my example I dont use any python-evdev. Documentation for writing this test program Im getting in Linux Kernel.

kharlashkin avatar May 14 '17 17:05 kharlashkin

ok. tested with fftest from linuxconsole package

only works throught USB cable

fails with BT due unimplemented function

└───╼  fftest /dev/input/event7
Force feedback test program.
HOLD FIRMLY YOUR WHEEL OR JOYSTICK TO PREVENT DAMAGES

Device /dev/input/event7 opened
Features:
  * Absolute axes: X, Y, Z, RX, RY, RZ, Throttle, Rudder, Wheel, Hat 0 X, Hat 0 Y, Distance, Tilt X, Tilt Y, 
    [FF 01 03 0E 00 00 00 00 ]
  * Relative axes: 
    [00 00 ]
  * Force feedback effects types: 
    Force feedback periodic effects: 
    [00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ]
  * Number of simultaneous effects: 0

Uploading effect #0 (Periodic sinusoidal) ... Error:: Function not implemented
Uploading effect #1 (Constant) ... Error: Function not implemented
Uploading effect #2 (Spring) ... Error: Function not implemented
Uploading effect #3 (Damper) ... Error: Function not implemented
Uploading effect #4 (Strong rumble, with heavy motor) ... Error: Function not implemented
Uploading effect #5 (Weak rumble, with light motor) ... Error: Function not implemented
Enter effect number, -1 to exit
-1
Stopping effects

same output with ds4drv --hidraw (with USB cable) (/dev/input/event25)

EDIT: oh, is a python2 (fails with python3) script..... ok. now works.

fails in BT mode throught ds4drv (plain bluez)

works in BT mode without ds4drv

sl1pkn07 avatar May 14 '17 19:05 sl1pkn07

Yes. I posted my script with idea to developers added vibration in ds4drv.

kharlashkin avatar May 14 '17 19:05 kharlashkin

you can add python3 support in you script?

sl1pkn07 avatar May 14 '17 21:05 sl1pkn07

Yes, I can add python3 support, but now I dont have a gamepad for testing.

kharlashkin avatar May 15 '17 04:05 kharlashkin

For anyone looking for Python 3 support: Just change line 11 to this:

self.ff_joy = open(file, "r+b", buffering=0)

Thanks for the Vibrate Class Kharlashkin

AndersGMadsen avatar Sep 18 '18 20:09 AndersGMadsen

This is my output on Fedora:

  File "rumble.py", line 53, in <module>
    p = f.new_effect(1.0, 1.0, TIME_DELTA )
  File "rumble.py", line 20, in new_effect
    fcntl.ioctl(self.ff_joy, EVIOCSFF, a, True)
OSError: [Errno 38] Function not implemented

@kharlashkin do you still need some testing for this? I can be a tester for this feature ;)

orwell1984 avatar Aug 16 '19 13:08 orwell1984

Hi there, anyone figured this out yet?

ror6ax avatar Mar 15 '20 00:03 ror6ax