knulli-cfw / distribution

Main KNULLI distribution
https://knulli.org
Other
351 stars 25 forks source link

Analog sticks deadzone fix #106

Open 00svd00 opened 1 month ago

00svd00 commented 1 month ago

Knulli build version

40-dev-d3b520f949 2024/07/21 02:18

Your architecture

RG35XX H

Issue description

We now can fix issies with analog sticks using modded kernel from this repo https://github.com/TheGammaSqueeze/40xx-kernel-decomp/releases

Detailed reproduction steps

  1. Dump, repack and reflash kernel. Linux PC needed 1.1 If your sdcard is /dev/sdb then sudo dd if=/dev/sdb1 bs=4M of=path/to/kerneldump.img 1.2 Repack it with modded kernel abootimg -x kerneldump.img abootimg --create newboot.img -f bootimg.cfg -k RG35XXH-kernel.modded -r initrd.img 1.3 Flash it back. sudo dd if=newboot.img of=/dev/sdb1 bs=4M
  2. Sticks will work, but they will be uncalibrated, To resolve this proble I've used script from this repo. https://github.com/m-kostrzewa/sdl2-joystick-calib with some modifications After this point everything should be done with ssh or scp on runnig console 2.1 create /opt/sdl2_jscal/sdl2-joystick-calib.py
    
    #!/usr/bin/python3

import argparse import logging as log from select import select

from evdev import InputDevice, UInput, UInputError

MOVED_EVENT = 3 #event type 3 is input from sticks and arrowkeys MAP_EVENT_CODE_TO_AXIS_IDX = { 1: 0, # left X (ABS_Z) 2: 1, # left Y (ABS_Y) 4: 2, # right X (ABS_RZ) 5: 3, # right Y (ABS_RY) 16: 4, #arrowkeys left\right 17: 5 #arrowkeys up\down }

class Calibration(object): def init(self, a, b, c, d): self.a = a self.b = b self.c = c self.d = d

def apply(self, real_pos):
    # y = sign*multiplier(deadzone-real_pos)
    x = real_pos
    y = 0
    if x < self.a:
        y = -self.c * (self.a - x) / 100000
    elif x > self.b:
        y = self.d * (x - self.b) / 100000

    return round(y)

def __str__(self):
    return "a: {}, b: {}, c: {}, d: {}". format(self.a, self.b, self.c, self.d)

def parse_params(): parser = argparse.ArgumentParser(description='Process some integers.') parser.add_argument('--input_dev', type=str, default='/dev/input/event1', help='input event device') parser.add_argument('--calib_file', type=str, default='cal.txt', help='jcal calibration file') parser.add_argument('--verbose', action='store_true', help='print verbose debugging output') parser.add_argument('--filter_evcode', type=int, default=-1, help='prints events only for speficic evcode') parser.add_argument('--dry_run', action='store_true', help='do not apply calibration, just pass through') args = parser.parse_args() return args

def setup_logging(is_verbose): if is_verbose: log.basicConfig(level=log.DEBUG) else: log.basicConfig(level=log.INFO)

def load_calibrations(calib_path): calibrations = {} with open(calib_path, "r") as f: line = f.readline()

    _, _, lotsa_numbers, _ = line.split(" ")
    calibs = lotsa_numbers.split(",")

    num_axis = int(calibs[0])

    current_axis = 0
    for i in range(1, len(calibs), 6):
        _, _, a, b, c, d = map(int, calibs[i:i+6])
        calibrations[current_axis] = Calibration(a, b, c, d)
        current_axis += 1

    assert(len(calibrations) == num_axis)

    log.info("Loaded calibration for axis:")
    for i in range(num_axis):
        log.info("- axis {}: {}".format(i, calibrations[i]))
return calibrations

def setup_devices(original_path): raw = InputDevice(original_path) target_dev = '/dev/uinput' try: fixed = UInput.from_device(raw, devnode=target_dev, name="Calibrated {}".format(raw.name)) except UInputError as e: raise PermissionError("You should run this command as root") from e log.info("Redirecting fixed stream to {}".format(target_dev)) return raw, fixed

def write_event(device, event): device.write_event(event) device.syn()

def redirect(from_dev, to_dev, calib, dry_run, filterevcode): while True: r, , _ = select([from_dev], [], []) for event in from_dev.read(): if event.type != MOVED_EVENT: write_event(to_dev, event) continue

        axis = MAP_EVENT_CODE_TO_AXIS_IDX[event.code]
        old_val = event.value
        new_val = calib[axis].apply(old_val) if not dry_run else old_val

        if filter_evcode == -1 or event.code == filter_evcode:
            log.debug('{}\t-> Adjusted value: {}'.format(event, new_val))

        event.value = new_val
        write_event(to_dev, event)

def main(): args = parse_params() setup_logging(args.verbose) calib = load_calibrations(args.calib_file) from_dev, to_dev = setup_devices(args.input_dev) redirect(from_dev, to_dev, calib, args.dry_run, args.filter_evcode)

if name == "main": main()

chmod +x /opt/sdl2_jscal/sdl2-joystick-calib.py
2.2 and /opt/sdl2_jscal/cal.txt

jscal -s 6,0,0,-300,800,145000,170000,0,0,-300,500,150000,180000,1,0,-600,400,170000,160000,1,0,-600,400,205000,135000,1,0,0,0,2147483647,2147483647,1,0,0,0,2147483647,2147483647 /dev/input/js0

3. Modify /etc/profile to add new env at the beginning of file

export SDL_GAMECONTROLLERCONFIG="19000000010000000100000000010000,odroidgo2 joypad,a:b1,b:b0,dpdown:b7,dpleft:b8,dpright:b9,dpup:b6,guide:b10,leftshoulder:b4,leftstick:b12,lefttrigger:b11,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b13,righttrigger:b14,start:b15,x:b2,y:b3,platform:Linux, 03000000010000000100000001000000,odroidgo2 joypad,a:b1,b:b0,dpdown:b7,dpleft:b8,dpright:b9,dpup:b6,guide:b10,leftshoulder:b4,leftstick:b12,lefttrigger:b11,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b13,righttrigger:b14,start:b15,x:b2,y:b3,platform:Linux, "

4.  add new script  /etc/init.d/S99sdljscal to run new srvice at boot

!/bin/sh

workfolder=/opt/sdl2_jscal mkdir /inputmirror mount -o bind /dev/input /inputmirror "$workfolder"/sdl2-joystick-calib.py --calib "$workfolder"/cal.txt --input "/inputmirror/event1" & counter=30 while [ ! -e /dev/input/event3 ]&&[ $counter -gt 0 ]; do sleep 1; counter=$(($counter-1)); done mount -o bind /inputmirror/event3 /dev/input/event1


chmod +x /etc/init.d/S99sdljscal
this script will replace real hradware gamepad with virtual one with corrected inputs
5. fix changes in firmware 
batocera-save-overlay
sync
reboot

### Details of any attempts to fix this yourself

Lots of different attempts. One of them worked

### Details of any modifications you have made to Knulli.

New kernel flashed. New service created

### Logs and data

_No response_
jbbandos commented 1 month ago

On my RG35XXH this messed up the button mappings. I now had select and start as "up" and "down", L1 as "select", and R1 as "start". East and North moved 3 lines down and up respectively. Nothing else worked... Removing the start-up script brought it back to normal.

00svd00 commented 1 month ago

On my RG35XXH this messed up the button mappings. I now had select and start as "up" and "down", L1 as "select", and R1 as "start". East and North moved 3 lines down and up respectively. Nothing else worked... Removing the start-up script brought it back to normal.

Seems that third paraghraph (/etc/profile modification) did not worked for you. We set button mappings for new virtual gamepad through SDL_GAMECONTROLLERCONFIG environment variable What is your output of sdl2-jstest --list ? Should be:

[root@KNULLI /userdata/system]# sdl2-jstest --list
Found 1 joystick(s)

Joystick Name:     'Calibrated Deeplay-keys'
Joystick Path:     '/dev/input/event1'
Joystick GUID:     03000000010000000100000001000000
Joystick Number:    0
Number of Axes:     4
Number of Buttons: 17
Number of Hats:     1
Number of Balls:    0
GameControllerConfig:
  Name:    'odroidgo2 joypad'
  Mapping: '03000000010000000100000001000000,odroidgo2 joypad,a:b1,b:b0,dpdown:b7,dpleft:b8,dpright:b9,dpup:b6,guide:b10,leftshoulder:b4,leftstick:b12,lefttrigger:b11,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b13,righttrigger:b14,start:b15,x:b2,y:b3,platform:Linux,'
Axis code  0:    1
Axis code  1:    2
Axis code  2:    4
Axis code  3:    5
Button code  0:    1
Button code  1:   114
Button code  2:   115
Button code  3:   304
Button code  4:   305
Button code  5:   306
Button code  6:   307
Button code  7:   308
Button code  8:   309
Button code  9:   310
Button code 10:   311
Button code 11:   312
Button code 12:   313
Button code 13:   314
Button code 14:   315
Button code 15:   316
Button code 16:   354
Hat code  0:   -1
jbbandos commented 1 month ago

Seems to be the same, apart from the GUID:

bash-5.2# sdl2-jstest --list
Found 1 joystick(s)

Joystick Name:     'Deeplay-keys'
Joystick Path:     '/dev/input/event1'
Joystick GUID:     19000000010000000100000000010000
Joystick Number:    0
Number of Axes:     4
Number of Buttons: 17
Number of Hats:     1
Number of Balls:    0
GameControllerConfig:
  Name:    'odroidgo2 joypad'
  Mapping: '19000000010000000100000000010000,odroidgo2 joypad,a:b1,b:b0,dpdown:b7,dpleft:b8,dpright:b9,dpup:b6,guide:b10,leftshoulder:b4,leftstick:b12,lefttrigger:b11,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b13,righttrigger:b14,start:b15,x:b2,y:b3,platform:Linux,'
Axis code  0:    1
Axis code  1:    2
Axis code  2:    4
Axis code  3:    5
Button code  0:    1
Button code  1:   114
Button code  2:   115
Button code  3:   304
Button code  4:   305
Button code  5:   306
Button code  6:   307
Button code  7:   308
Button code  8:   309
Button code  9:   310
Button code 10:   311
Button code 11:   312
Button code 12:   313
Button code 13:   314
Button code 14:   315
Button code 15:   316
Button code 16:   354
Hat code  0:   -1
00svd00 commented 1 month ago

Seems to be the same, apart from the GUID:

You did not restore startup script before doing this, right? The idea of this hack is like:

  1. Create mirror of /dev/input ( mkdir /inputmirror and mount -o bind /dev/input /inputmirror commands)
  2. Run special script, which reads events from HW one (from /inputmirror/event1) and creates new virtual gamepad with calibrated input(/opt/sdl2_jscal/sdl2-joystick-calib.py --calib /opt/sdl2_jscal/cal.txt --input "/inputmirror/event1" & command)
  3. Mount new virtual gamepad (/dev/input/event3) on top of HW one to hide HW gamepad from system and inrtercept all readings (mount -o bind /inputmirror/event3 /dev/input/event1 command)

Unfortunately, there is no default key mappings for our virtual gamepad, so we provide it through SDL_GAMECONTROLLERCONFIG environment variable.

So, you should check your SDL_GAMECONTROLLERCONFIG variable echo $SDL_GAMECONTROLLERCONFIG Output should be:

[root@KNULLI /userdata/system]# echo $SDL_GAMECONTROLLERCONFIG
19000000010000000100000000010000,odroidgo2 joypad,a:b1,b:b0,dpdown:b7,dpleft:b8,dpright:b9,dpup:b6,guide:b10,leftshoulder:b4,leftstick:b12,lefttrigger:b11,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b13,righttrigger:b14,start:b15,x:b2,y:b3,platform:Linux, 03000000010000000100000001000000,odroidgo2 joypad,a:b1,b:b0,dpdown:b7,dpleft:b8,dpright:b9,dpup:b6,guide:b10,leftshoulder:b4,leftstick:b12,lefttrigger:b11,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b13,righttrigger:b14,start:b15,x:b2,y:b3,platform:Linux,

And also check your /etc/profile Should be like:

export SDL_GAMECONTROLLERCONFIG="19000000010000000100000000010000,odroidgo2 joypad,a:b1,b:b0,dpdown:b7,dpleft:b8,dpright:b9,dpup:b6,guide:b10,leftshoulder:b4,leftstick:b12,lefttrigger:b11,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b13,righttrigger:b14,start:b15,x:b2,y:b3,platform:Linux,
03000000010000000100000001000000,odroidgo2 joypad,a:b1,b:b0,dpdown:b7,dpleft:b8,dpright:b9,dpup:b6,guide:b10,leftshoulder:b4,leftstick:b12,lefttrigger:b11,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b13,righttrigger:b14,start:b15,x:b2,y:b3,platform:Linux,
"
if [ "$PS1" ]; then
    if [ "`id -u`" -eq 0 ]; then
        export PS1='# '
    else
        export PS1='$ '
    fi
fi

export EDITOR='/bin/vi'

# Source configuration files from /etc/profile.d
for i in /etc/profile.d/*.sh ; do
    if [ -r "$i" ]; then
        . $i
    fi
done
unset i

Also dowble check, that all files, which you modified or created now have linux line-ending (Windows OS uses combination of CR and LF as line end, MacOS uses CR only and Linux uses only LF) After that reatore all scripts and try again

jbbandos commented 1 month ago
[root@KNULLI /userdata/system]# echo $SDL_GAMECONTROLLERCONFIG
19000000010000000100000000010000,odroidgo2 joypad,a:b1,b:b0,dpdown:b7,dpleft:b8,dpright:b9,dpup:b6,guide:b10,leftshoulder:b4,leftstick:b12,lefttrigger:b11,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b13,righttrigger:b14,start:b15,x:b2,y:b3,platform:Linux, 03000000010000000100000001000000,odroidgo2 joypad,a:b1,b:b0,dpdown:b7,dpleft:b8,dpright:b9,dpup:b6,guide:b10,leftshoulder:b4,leftstick:b12,lefttrigger:b11,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b13,righttrigger:b14,start:b15,x:b2,y:b3,platform:Linux,
[root@KNULLI /userdata/system]# cat /etc/profile
export PATH="/bin:/sbin:/usr/bin:/usr/sbin"

if [ "$PS1" ]; then
    if [ "`id -u`" -eq 0 ]; then
        export PS1='# '
    else
        export PS1='$ '
    fi
fi

export EDITOR='/bin/vi'

# Source configuration files from /etc/profile.d
for i in /etc/profile.d/*.sh ; do
    if [ -r "$i" ]; then
        . $i
    fi
done
unset i

export SDL_GAMECONTROLLERCONFIG="19000000010000000100000000010000,odroidgo2 joypad,a:b1,b:b0,dpdown:b7,dpleft:b8,dpright:b9,dpup:b6,guide:b10,leftshoulder:b4,leftstick:b12,lefttrigger:b11,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b13,righttrigger:b14,start:b15,x:b2,y:b3,platform:Linux,
03000000010000000100000001000000,odroidgo2 joypad,a:b1,b:b0,dpdown:b7,dpleft:b8,dpright:b9,dpup:b6,guide:b10,leftshoulder:b4,leftstick:b12,lefttrigger:b11,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b13,righttrigger:b14,start:b15,x:b2,y:b3,platform:Linux,
"

Everything was done on the terminal, with vim, so it should have a LF line ending only. I see that /etc/profile I've put the "export SDL_GAMECONTROLLERCONFIG" line at the end, I'll move it to the beginning

00svd00 commented 1 month ago

export SDL_GAMECONTROLLERCONFIG" line at the end

I think it should not make any difference, but try it. If nothing works - I will publish all files from my installation