chrippa / ds4drv

A Sony DualShock 4 userspace driver for Linux
MIT License
1.05k stars 213 forks source link

Rumble support #91

Open Ape opened 8 years ago

Ape commented 8 years ago

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.

poconbhui commented 8 years ago

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

Ape commented 8 years ago

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.

kharlashkin commented 8 years ago

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))
Millsionaire commented 8 years ago

@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!

kharlashkin commented 8 years ago

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

jrahlf commented 7 years ago

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.

logos88 commented 7 years ago

Can't this be done through libinput?

sl1pkn07 commented 7 years ago

@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

kharlashkin commented 7 years ago

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 commented 7 years ago

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

sl1pkn07 commented 7 years ago

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

kharlashkin commented 7 years ago

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.

sl1pkn07 commented 7 years ago

then only works with USB? not working through BT?

kharlashkin commented 7 years ago

On occasion, I will ask him about BT.

sl1pkn07 commented 7 years ago

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

kharlashkin commented 7 years ago

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

sl1pkn07 commented 7 years ago

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

kharlashkin commented 7 years ago

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

sl1pkn07 commented 7 years ago

you can add python3 support in you script?

kharlashkin commented 7 years ago

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

gjoelbye commented 6 years ago

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

orwell1984 commented 5 years ago

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 ;)

ror6ax commented 4 years ago

Hi there, anyone figured this out yet?