Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable the DualShock 2 controller #22

Open
6 of 16 tasks
frno7 opened this issue Mar 17, 2019 · 35 comments
Open
6 of 16 tasks

Enable the DualShock 2 controller #22

frno7 opened this issue Mar 17, 2019 · 35 comments
Labels
enhancement New feature or request help wanted Extra attention is needed

Comments

@frno7
Copy link
Owner

frno7 commented Mar 17, 2019

Implement a device driver for the DualShock 2 controller. See also #11. Plan:

  • one DualShock 2 controller;
  • two DualShock 2 controllers;
  • regular polling, for example at 200 Hz;
  • state change detection to avoid needless EE interrupts;
  • reduce polling to 10 Hz or so when controllers are idle for a long time;
  • define and implement a suitable IOP-EE SIO2 protocol;
  • implement an input event Linux kernel device driver;
  • indicate whether controllers are attached or detached;
  • handle errors, such as timeouts and failures of various kinds;
  • conclude whether SIO2 DMA makes sense for controllers;
  • motor (rumble) control;
  • switch between digital and analogue controls;
  • recognise 256 pressure levels for all buttons except for the analog mode, start, select, L3 and R3;
  • recognise controllers other than DualShock 2;
  • consider naming the module sio2controller, or suchlike, as that’d be more specific than gamepad;
  • multitap.
@frno7 frno7 added the enhancement New feature or request label Mar 17, 2019
frno7 pushed a commit that referenced this issue May 10, 2019
commit bafdf85 upstream.

Move ieee80211_tx_status_ext() outside of status_list lock section
in order to avoid locking dependency and possible deadlock reposed by
LOCKDEP in below warning.

Also do mt76_tx_status_lock() just before it's needed.

[  440.224832] WARNING: possible circular locking dependency detected
[  440.224833] 5.1.0-rc2+ #22 Not tainted
[  440.224834] ------------------------------------------------------
[  440.224835] kworker/u16:28/2362 is trying to acquire lock:
[  440.224836] 0000000089b8cacf (&(&q->lock)->rlock#2){+.-.}, at: mt76_wake_tx_queue+0x4c/0xb0 [mt76]
[  440.224842]
               but task is already holding lock:
[  440.224842] 000000002cfedc59 (&(&sta->lock)->rlock){+.-.}, at: ieee80211_stop_tx_ba_cb+0x32/0x1f0 [mac80211]
[  440.224863]
               which lock already depends on the new lock.

[  440.224863]
               the existing dependency chain (in reverse order) is:
[  440.224864]
               -> #3 (&(&sta->lock)->rlock){+.-.}:
[  440.224869]        _raw_spin_lock_bh+0x34/0x40
[  440.224880]        ieee80211_start_tx_ba_session+0xe4/0x3d0 [mac80211]
[  440.224894]        minstrel_ht_get_rate+0x45c/0x510 [mac80211]
[  440.224906]        rate_control_get_rate+0xc1/0x140 [mac80211]
[  440.224918]        ieee80211_tx_h_rate_ctrl+0x195/0x3c0 [mac80211]
[  440.224930]        ieee80211_xmit_fast+0x26d/0xa50 [mac80211]
[  440.224942]        __ieee80211_subif_start_xmit+0xfc/0x310 [mac80211]
[  440.224954]        ieee80211_subif_start_xmit+0x38/0x390 [mac80211]
[  440.224956]        dev_hard_start_xmit+0xb8/0x300
[  440.224957]        __dev_queue_xmit+0x7d4/0xbb0
[  440.224968]        ip6_finish_output2+0x246/0x860 [ipv6]
[  440.224978]        mld_sendpack+0x1bd/0x360 [ipv6]
[  440.224987]        mld_ifc_timer_expire+0x1a4/0x2f0 [ipv6]
[  440.224989]        call_timer_fn+0x89/0x2a0
[  440.224990]        run_timer_softirq+0x1bd/0x4d0
[  440.224992]        __do_softirq+0xdb/0x47c
[  440.224994]        irq_exit+0xfa/0x100
[  440.224996]        smp_apic_timer_interrupt+0x9a/0x220
[  440.224997]        apic_timer_interrupt+0xf/0x20
[  440.224999]        cpuidle_enter_state+0xc1/0x470
[  440.225000]        do_idle+0x21a/0x260
[  440.225001]        cpu_startup_entry+0x19/0x20
[  440.225004]        start_secondary+0x135/0x170
[  440.225006]        secondary_startup_64+0xa4/0xb0
[  440.225007]
               -> #2 (&(&sta->rate_ctrl_lock)->rlock){+.-.}:
[  440.225009]        _raw_spin_lock_bh+0x34/0x40
[  440.225022]        rate_control_tx_status+0x4f/0xb0 [mac80211]
[  440.225031]        ieee80211_tx_status_ext+0x142/0x1a0 [mac80211]
[  440.225035]        mt76x02_send_tx_status+0x2e4/0x340 [mt76x02_lib]
[  440.225037]        mt76x02_tx_status_data+0x31/0x40 [mt76x02_lib]
[  440.225040]        mt76u_tx_status_data+0x51/0xa0 [mt76_usb]
[  440.225042]        process_one_work+0x237/0x5d0
[  440.225043]        worker_thread+0x3c/0x390
[  440.225045]        kthread+0x11d/0x140
[  440.225046]        ret_from_fork+0x3a/0x50
[  440.225047]
               -> #1 (&(&list->lock)->rlock#8){+.-.}:
[  440.225049]        _raw_spin_lock_bh+0x34/0x40
[  440.225052]        mt76_tx_status_skb_add+0x51/0x100 [mt76]
[  440.225054]        mt76x02u_tx_prepare_skb+0xbd/0x116 [mt76x02_usb]
[  440.225056]        mt76u_tx_queue_skb+0x5f/0x180 [mt76_usb]
[  440.225058]        mt76_tx+0x93/0x190 [mt76]
[  440.225070]        ieee80211_tx_frags+0x148/0x210 [mac80211]
[  440.225081]        __ieee80211_tx+0x75/0x1b0 [mac80211]
[  440.225092]        ieee80211_tx+0xde/0x110 [mac80211]
[  440.225105]        __ieee80211_tx_skb_tid_band+0x72/0x90 [mac80211]
[  440.225122]        ieee80211_send_auth+0x1f3/0x360 [mac80211]
[  440.225141]        ieee80211_auth.cold.40+0x6c/0x100 [mac80211]
[  440.225156]        ieee80211_mgd_auth.cold.50+0x132/0x15f [mac80211]
[  440.225171]        cfg80211_mlme_auth+0x149/0x360 [cfg80211]
[  440.225181]        nl80211_authenticate+0x273/0x2e0 [cfg80211]
[  440.225183]        genl_family_rcv_msg+0x196/0x3a0
[  440.225184]        genl_rcv_msg+0x47/0x8e
[  440.225185]        netlink_rcv_skb+0x3a/0xf0
[  440.225187]        genl_rcv+0x24/0x40
[  440.225188]        netlink_unicast+0x16d/0x210
[  440.225189]        netlink_sendmsg+0x204/0x3b0
[  440.225191]        sock_sendmsg+0x36/0x40
[  440.225193]        ___sys_sendmsg+0x259/0x2b0
[  440.225194]        __sys_sendmsg+0x47/0x80
[  440.225196]        do_syscall_64+0x60/0x1f0
[  440.225197]        entry_SYSCALL_64_after_hwframe+0x49/0xbe
[  440.225198]
               -> #0 (&(&q->lock)->rlock#2){+.-.}:
[  440.225200]        lock_acquire+0xb9/0x1a0
[  440.225202]        _raw_spin_lock_bh+0x34/0x40
[  440.225204]        mt76_wake_tx_queue+0x4c/0xb0 [mt76]
[  440.225215]        ieee80211_agg_start_txq+0xe8/0x2b0 [mac80211]
[  440.225225]        ieee80211_stop_tx_ba_cb+0xb8/0x1f0 [mac80211]
[  440.225235]        ieee80211_ba_session_work+0x1c1/0x2f0 [mac80211]
[  440.225236]        process_one_work+0x237/0x5d0
[  440.225237]        worker_thread+0x3c/0x390
[  440.225239]        kthread+0x11d/0x140
[  440.225240]        ret_from_fork+0x3a/0x50
[  440.225240]
               other info that might help us debug this:

[  440.225241] Chain exists of:
                 &(&q->lock)->rlock#2 --> &(&sta->rate_ctrl_lock)->rlock --> &(&sta->lock)->rlock

[  440.225243]  Possible unsafe locking scenario:

[  440.225244]        CPU0                    CPU1
[  440.225244]        ----                    ----
[  440.225245]   lock(&(&sta->lock)->rlock);
[  440.225245]                                lock(&(&sta->rate_ctrl_lock)->rlock);
[  440.225246]                                lock(&(&sta->lock)->rlock);
[  440.225247]   lock(&(&q->lock)->rlock#2);
[  440.225248]
                *** DEADLOCK ***

[  440.225249] 5 locks held by kworker/u16:28/2362:
[  440.225250]  #0: 0000000048fcd291 ((wq_completion)phy0){+.+.}, at: process_one_work+0x1b5/0x5d0
[  440.225252]  #1: 00000000f1c6828f ((work_completion)(&sta->ampdu_mlme.work)){+.+.}, at: process_one_work+0x1b5/0x5d0
[  440.225254]  #2: 00000000433d2b2c (&sta->ampdu_mlme.mtx){+.+.}, at: ieee80211_ba_session_work+0x5c/0x2f0 [mac80211]
[  440.225265]  #3: 000000002cfedc59 (&(&sta->lock)->rlock){+.-.}, at: ieee80211_stop_tx_ba_cb+0x32/0x1f0 [mac80211]
[  440.225276]  #4: 000000009d7b9a44 (rcu_read_lock){....}, at: ieee80211_agg_start_txq+0x33/0x2b0 [mac80211]
[  440.225286]
               stack backtrace:
[  440.225288] CPU: 2 PID: 2362 Comm: kworker/u16:28 Not tainted 5.1.0-rc2+ #22
[  440.225289] Hardware name: LENOVO 20KGS23S0P/20KGS23S0P, BIOS N23ET55W (1.30 ) 08/31/2018
[  440.225300] Workqueue: phy0 ieee80211_ba_session_work [mac80211]
[  440.225301] Call Trace:
[  440.225304]  dump_stack+0x85/0xc0
[  440.225306]  print_circular_bug.isra.38.cold.58+0x15c/0x195
[  440.225307]  check_prev_add.constprop.48+0x5f0/0xc00
[  440.225309]  ? check_prev_add.constprop.48+0x39d/0xc00
[  440.225311]  ? __lock_acquire+0x41d/0x1100
[  440.225312]  __lock_acquire+0xd98/0x1100
[  440.225313]  ? __lock_acquire+0x41d/0x1100
[  440.225315]  lock_acquire+0xb9/0x1a0
[  440.225317]  ? mt76_wake_tx_queue+0x4c/0xb0 [mt76]
[  440.225319]  _raw_spin_lock_bh+0x34/0x40
[  440.225321]  ? mt76_wake_tx_queue+0x4c/0xb0 [mt76]
[  440.225323]  mt76_wake_tx_queue+0x4c/0xb0 [mt76]
[  440.225334]  ieee80211_agg_start_txq+0xe8/0x2b0 [mac80211]
[  440.225344]  ieee80211_stop_tx_ba_cb+0xb8/0x1f0 [mac80211]
[  440.225354]  ieee80211_ba_session_work+0x1c1/0x2f0 [mac80211]
[  440.225356]  process_one_work+0x237/0x5d0
[  440.225358]  worker_thread+0x3c/0x390
[  440.225359]  ? wq_calc_node_cpumask+0x70/0x70
[  440.225360]  kthread+0x11d/0x140
[  440.225362]  ? kthread_create_on_node+0x40/0x40
[  440.225363]  ret_from_fork+0x3a/0x50

Cc: stable@vger.kernel.org
Fixes: 88046b2 ("mt76: add support for reporting tx status with skb")
Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
Acked-by: Felix Fietkau <nbd@nbd.name>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
frno7 pushed a commit that referenced this issue Sep 1, 2019
KASAN report this:

kernel BUG at net/mac802154/main.c:130!
invalid opcode: 0000 [#1] PREEMPT SMP
CPU: 0 PID: 19932 Comm: modprobe Not tainted 5.1.0-rc6+ #22
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.9.3-0-ge2fc41e-prebuilt.qemu-project.org 04/01/2014
RIP: 0010:ieee802154_free_hw+0x2a/0x30 [mac802154]
Code: 55 48 8d 57 38 48 89 e5 53 48 89 fb 48 8b 47 38 48 39 c2 75 15 48 8d 7f 48 e8 82 85 16 e1 48 8b 7b 28 e8 f9 ef 83 e2 5b 5d c3 <0f> 0b 0f 1f 40 00 55 48 89 e5 53 48 89 fb 0f b6 86 80 00 00 00 88
RSP: 0018:ffffc90001c7b9f0 EFLAGS: 00010206
RAX: ffff88822df3aa80 RBX: ffff88823143d5c0 RCX: 0000000000000002
RDX: ffff88823143d5f8 RSI: ffff88822b1fabc0 RDI: ffff88823143d5c0
RBP: ffffc90001c7b9f8 R08: 0000000000000000 R09: 0000000000000001
R10: 0000000000000000 R11: 0000000000000000 R12: 00000000fffffff4
R13: ffff88822dea4f50 R14: ffff88823143d7c0 R15: 00000000fffffff4
FS: 00007ff52e999540(0000) GS:ffff888237a00000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00007fdc06dba768 CR3: 000000023160a000 CR4: 00000000000006f0
Call Trace:
 hwsim_add_one+0x2dd/0x540 [mac802154_hwsim]
 hwsim_probe+0x2f/0xb0 [mac802154_hwsim]
 platform_drv_probe+0x3a/0x90
 ? driver_sysfs_add+0x79/0xb0
 really_probe+0x1d4/0x2d0
 driver_probe_device+0x50/0xf0
 device_driver_attach+0x54/0x60
 __driver_attach+0x7e/0xd0
 ? device_driver_attach+0x60/0x60
 bus_for_each_dev+0x68/0xc0
 driver_attach+0x19/0x20
 bus_add_driver+0x15e/0x200
 driver_register+0x5b/0xf0
 __platform_driver_register+0x31/0x40
 hwsim_init_module+0x74/0x1000 [mac802154_hwsim]
 ? 0xffffffffa00e9000
 do_one_initcall+0x6c/0x3cc
 ? kmem_cache_alloc_trace+0x248/0x3b0
 do_init_module+0x5b/0x1f1
 load_module+0x1db1/0x2690
 ? m_show+0x1d0/0x1d0
 __do_sys_finit_module+0xc5/0xd0
 __x64_sys_finit_module+0x15/0x20
 do_syscall_64+0x6b/0x1d0
 entry_SYSCALL_64_after_hwframe+0x49/0xbe
RIP: 0033:0x7ff52e4a2839
Code: 00 f3 c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 40 00 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 8b 0d 1f f6 2c 00 f7 d8 64 89 01 48
RSP: 002b:00007ffffa7b3c08 EFLAGS: 00000246 ORIG_RAX: 0000000000000139
RAX: ffffffffffffffda RBX: 00005647560a2a00 RCX: 00007ff52e4a2839
RDX: 0000000000000000 RSI: 00005647547f3c2e RDI: 0000000000000003
RBP: 00005647547f3c2e R08: 0000000000000000 R09: 00005647560a2a00
R10: 0000000000000003 R11: 0000000000000246 R12: 0000000000000000
R13: 00005647560a2c10 R14: 0000000000040000 R15: 00005647560a2a00
Modules linked in: mac802154_hwsim(+) mac802154 [last unloaded: mac802154_hwsim]

In hwsim_add_one, if hwsim_subscribe_all_others fails, we
should call ieee802154_unregister_hw to free resources.

Reported-by: Hulk Robot <hulkci@huawei.com>
Fixes: f25da51 ("ieee802154: hwsim: add replacement for fakelb")
Signed-off-by: YueHaibing <yuehaibing@huawei.com>
Acked-by: Alexander Aring <aring@mojatatu.com>
Signed-off-by: Stefan Schmidt <stefan@datenfreihafen.org>
@frno7
Copy link
Owner Author

frno7 commented Jun 14, 2020

Is anyone aware of complete and detailed hardware documentation of the IOP SIO2? Including interrupts and use of DMA? With good naming conventions for all register bits?

A selection of incomplete references is ps2tek and PS2SDK.

Nocash PSX-SPX describes related registers for the PS1, but SIO2 is apparently specific for the PS2.

@frno7 frno7 added the help wanted Extra attention is needed label Jun 14, 2020
@AKuHAK
Copy link

AKuHAK commented Jun 16, 2020

You can check this header file .
More info discussed here .
Maybe @rickgaiser can give more info on it.

@rickgaiser
Copy link

I was actually watching this issue hoping to get more information. The information in the header file is created by wisi.

@frno7
Copy link
Owner Author

frno7 commented Jun 16, 2020

Thanks @AKuHAK & @rickgaiser! My plan is to begin to use SIO2 with DMA for the DualShock controller, and then make the SIO2 part more general for #21. I expect reading and writing memory cards to be more complex.

To improve performance, the plan is also to have the IOP notify the EE about gamepads only when there are actual state changes, such as someone pressing a button. This could significantly lower controller latency too, and means not asserting gamepad interrupts regularly, such as every video frame or similar.

@frno7
Copy link
Owner Author

frno7 commented Jun 20, 2020

I have gathered the relevant SIO2 references I could find, especially via notes by Wisi, and defined sio2.h with the best address and bit field identifiers I could come up with. @AKuHAK and @rickgaiser, do you have any comments on those?

Note: All of these files are technically in the iopmod repo, and not in this Linux repo, so maybe we ought to move the IOP part of this discussion to that repo?

I have also made a provisional gamepad.c IOP module with a simple loop printing SIO2 register values to the Linux kernel log, and it looks reasonable to me:

iop: gamepad: PORT0_CTRL0 c0c0050f
iop: gamepad: PORT0_CTRL1  1060014
iop: gamepad: PORT1_CTRL0 c0c0050f
iop: gamepad: PORT1_CTRL1  1060014
iop: gamepad: PORT2_CTRL0 c0c0050f
iop: gamepad: PORT2_CTRL1  1060014
iop: gamepad: PORT3_CTRL0 c0c0050f
iop: gamepad: PORT3_CTRL1  1060014
iop: gamepad:          TX        0
iop: gamepad:          RX ffffffff
iop: gamepad:        CTRL      3b0
iop: gamepad:    CMD_STAT    15000
iop: gamepad:   PORT_STAT        f
iop: gamepad:   FIFO_STAT  8000000
iop: gamepad:     FIFO_TX        0
iop: gamepad:     FIFO_RX        0
iop: gamepad:    IRQ_STAT        0

Unfortunately, trying to register the SIO2 IRQ fails with

iop: gamepad_init: request_irq for IRQ_IOP_SIO2 failed with -16

where -16 means errno EBUSY. I suppose that is to be expected, given that

# cat /sys/firmware/iop/*/name | grep -i sio
sio2man

indicates that the IOP module SIO2MAN is loaded, which collides with the SIO2 handling I’m about to implement. So SIO2MAN must be unloaded, or not loaded to begin with. I suspect that it comes via rom0:OSDCNF in

#define IOP_RESET_ARGS "rom0:UDNL rom0:OSDCNF"

which is the topic of #28, and more specifically the issue of implementing Mr Brown’s SBV LoadModuleBuffer patch linked in #28 (comment). @AKuHAK, what are your thoughts?

@frno7
Copy link
Owner Author

frno7 commented Jul 4, 2020

With issue #28 just about finished, simple operations on the SIO2 hardware registers appear to complete as expected. The controller polling command 0x01 0x42 0x00 returns the anticipated 0xff 0x41 0x5a 0xff 0xff, with the SIO2 interrupt asserted and SIO2 FIFO registers updated accordingly. With printk in the IRQ handler in the SIO2 IRX module:

iop: sio2: PORT0_CTRL0 ff600a0a
iop: sio2: PORT0_CTRL1    20014
iop: sio2: PORT1_CTRL0 ffc00505
iop: sio2: PORT1_CTRL1    2000a
iop: sio2: PORT2_CTRL0        0
iop: sio2: PORT2_CTRL1        0
iop: sio2: PORT3_CTRL0        0
iop: sio2: PORT3_CTRL1        0
iop: sio2:        CTRL      390
iop: sio2:    CMD_STAT     1100
iop: sio2:   PORT_STAT        f
iop: sio2:   FIFO_STAT    50000
iop: sio2:     FIFO_TX    50005
iop: sio2:     FIFO_RX        5
iop: sio2:    IRQ_STAT        1
iop: sio2:   tx buffer 01 42 00 00 00 00 00 00 ...
iop: sio2:   rx buffer ff 41 5a ff ff 00 00 00 ...

I’ve added a list of remains-to-be-done boxes as an implementation plan in the description of this issue.

@frno7
Copy link
Owner Author

frno7 commented Jul 5, 2020

Curiously, PS2SDK has notes in timrman.h that PADMAN reserves two timers for its task, but I suppose it shares them with others using VBLANK and HBLANK. HBLANK usually runs rather often, though, at 10+ kHz and seems best to avoid.

I’m considering polling controllers with SetAlarm in THBASE at about 200 Hz instead, in combination with a SIO2 IRQ handler. Any controller latency ought to be imperceptible at that rate. With a 250 kHz SIO2 baud rate that would be a maximum of 156 bytes per poll, or twice the amount at 500 kHz. I assume the worst case is 8 simultaneous controllers via multitap. Perhaps it would be best with an adaptable polling rate, so that one or two controllers are optimal at 200 Hz and won’t suffer any latency for the unusual worst case of having 8 controllers.

Then eventually controllers and memory cards (issue #21) must multiplex over the SIO2 with minimum latency for the controllers and maximum bandwidth for the memory cards.

@frno7
Copy link
Owner Author

frno7 commented Jul 6, 2020

Thanks, @sp193! I’m moving the discussion to this issue, since issue #28 will close and applications of timers are more relevant here.

By documentation, it may only be executed from a thread. The newer SDKs have GetSystemTimeLow(), which Sony documented as a faster version that can also be invoked from interrupt handlers.

Would you know if someone has written reasonably complete and publicly available documentation for these and other functions? PS2SDK contains a lot of function declarations but I’m unable to find any reference manual or suchlike.

The USec2SysClock() and SysClock2USec() functions use these values to convert ticks to/from microseconds.

These will be useful, thanks! The plan is to write a state machine for the SIO2 and the controllers described in this issue. Timers will then be used, so that attached controllers are polled for instance every 5 ms whereas unattached ports are polled much less frequently at every 100 ms or so (to discover whether a controller is being attached). If more than 4 controllers are attached, polling could be reduced to 10 ms or perhaps 20 ms, to save SIO2 bandwidth. I expected timers to be crucial to multiplex the SIO2 fairly and efficiently.

@sp193
Copy link

sp193 commented Jul 6, 2020

Since it is a Sony console, only Sony has the most complete documentation. Other information can be derived from disassembling their modules.

The official PADMAN transfers data every frame to the EE. Games read the pad state from a buffer on the EE, so the SIO2 bus does not see more activity from the game checking on the pad state at an increased rate.

@frno7
Copy link
Owner Author

frno7 commented Jul 6, 2020

Since it is a Sony console, only Sony has the most complete documentation. Other information can be derived from disassembling their modules.

Right, so to use PS2SDK without Sony’s documentation one have to disassemble the modules and study the machine code. I assumed that was the case, but now I know, thanks!

The official PADMAN transfers data every frame to the EE. Games read the pad state from a buffer on the EE, so the SIO2 bus does not see more activity from the game checking on the pad state at an increased rate.

I believe that we can obtain subframe controller latency in the Linux kernel, as it won’t use PADMAN. With adaptable timers and controller state change detection on the IOP side, this should be more efficient too, especially for the EE.

@frno7
Copy link
Owner Author

frno7 commented Jul 7, 2020

@sp193, I’m considering writing up a reference manual for the IOP BIOS, starting with the subset used by the Linux kernel modules so far. The format would be RST. Perhaps this text could be shared with PS2SDK? Although different naming conventions are used, the semantics remain exactly the same.

@AKuHAK
Copy link

AKuHAK commented Jul 7, 2020

Ps2sdk lacks documentation, thats true. BTW Doxygen generates documentation from ps2sdk with each commit.
https://ps2dev.github.io/ps2sdk/

@frno7
Copy link
Owner Author

frno7 commented Jul 8, 2020

@AKuHAK, I’ve added issue #4 to Document IOP BIOS API used by modules. Hopefully we can choose a common reference documentation licence that is compatible with both PS2SDK and Linux, to effortlessly share that kind of text.

@frno7
Copy link
Owner Author

frno7 commented Jul 8, 2020

So far so good, with 5 out of 13 items done, as listed in the description! The SIO2 seems to behave as one could expect, when directly operating hardware registers (not using the official Sony SIO2MAN or PADMAN modules). The code certainly needs cleaning, but the controller fundamentals are there now.

@frno7
Copy link
Owner Author

frno7 commented Dec 15, 2020

Now 6 out of 13 are done, with a proper input event Linux kernel device driver in drivers/ps2/gamepad.c. The corresponding IOP module is module/gamepad.c, which is a SIO2 hardware driver not using Sony firmware.

Documentation remains to be written. And feature extensions, and cleanups. The standard evtest tool in Linux can now test gamepad input events, as applications would observe them. After the keyboard devices (not shown here), the two gamepad ports are listed, and I selected 4 for event4 since a controller happened to be connected to port 2:

/dev/input/event3:	PlayStation 2 gamepad 1
/dev/input/event4:	PlayStation 2 gamepad 2
Select the device event number [0-4]: 4

Various input device information is printed (bus, vendor and version ought to be filled in with something useful):

Input driver version is 1.0.1
Input device ID: bus 0x0 vendor 0x0 product 0x0 version 0x0
Input device name: "PlayStation 2 gamepad 2"

A list of the possible key code events is given, where BTN_SOUTH corresponds cross, BTN_EAST to circle, and so on:

Supported events:
  Event type 0 (EV_SYN)
  Event type 1 (EV_KEY)
    Event code 304 (BTN_SOUTH)
    Event code 305 (BTN_EAST)
    Event code 307 (BTN_NORTH)
    Event code 308 (BTN_WEST)
    Event code 310 (BTN_TL)
    Event code 311 (BTN_TR)
    Event code 312 (BTN_TL2)
    Event code 313 (BTN_TR2)
    Event code 314 (BTN_SELECT)
    Event code 315 (BTN_START)
    Event code 544 (BTN_DPAD_UP)
    Event code 545 (BTN_DPAD_DOWN)
    Event code 546 (BTN_DPAD_LEFT)
    Event code 547 (BTN_DPAD_RIGHT)
Properties:

Then evtest waits for input and pressing and releasing for example the cross, circle and START buttons prints the following:

Testing ... (interrupt to exit)
Event: time 1608053409.675738, type 1 (EV_KEY), code 304 (BTN_SOUTH), value 1
Event: time 1608053409.675738, -------------- SYN_REPORT ------------
Event: time 1608053409.899124, type 1 (EV_KEY), code 304 (BTN_SOUTH), value 0
Event: time 1608053409.899124, -------------- SYN_REPORT ------------
Event: time 1608053412.613564, type 1 (EV_KEY), code 305 (BTN_EAST), value 1
Event: time 1608053412.613564, -------------- SYN_REPORT ------------
Event: time 1608053412.738838, type 1 (EV_KEY), code 305 (BTN_EAST), value 0
Event: time 1608053412.738838, -------------- SYN_REPORT ------------
Event: time 1608053427.549995, type 1 (EV_KEY), code 315 (BTN_START), value 1
Event: time 1608053427.549995, -------------- SYN_REPORT ------------
Event: time 1608053427.735774, type 1 (EV_KEY), code 315 (BTN_START), value 0
Event: time 1608053427.735774, -------------- SYN_REPORT ------------

So two-player games with digital controllers are now possible.

I’m quite happy with how this driver turned out, so far. Especially that it is both event driven (not bothering the EE with nonevents), and has significantly lower latency (preliminary at about 5 ms), compared with the standard firmware.

@frno7
Copy link
Owner Author

frno7 commented Dec 31, 2021

The wiki now has a page on controllers.

@Arch91
Copy link

Arch91 commented Jan 21, 2022

Currently can not build iopmod branch "gamepad". I typed
make CROSS_COMPILE=mipsr5900el-unknown-linux-gnu-

  • and it asks for some likely absent file tool/version.c . No doubt I built a working cross-compiler.

@frno7
Copy link
Owner Author

frno7 commented Jan 22, 2022

@Arch91, maybe you’ve got a dangling dependency if you’ve switched branches. Have you tried make clean or git clean -fdx before compiling? Strictly speaking this would be an issue for the iopmod repo, but let’s hope it’ll be resolved with a simple cleaning. 😄

I should probably announce as well that the gamepad.ko kernel module probably will be renamed to controller.ko in the near future, since a gamepad is special kind of controller. Likewise with controller.irx for gamepad.irx. The code will also be merged with the main branch.

@Arch91
Copy link

Arch91 commented Jan 22, 2022

@frno7, I manually downloaded the source of the iopmod-gamepad branch as a zip-archive file and unpacked it at the same level where is the folder with the iopmod main branch. Should I download it by some git command instead?
I tried make clean and git clean -fdx. After the last one I got the same "fatal" notice as if I am trying to build:
"not a git repository (or any of the parent directories): .git"

@frno7
Copy link
Owner Author

frno7 commented Jan 22, 2022

Ah, yes, iopmod is meant to be compiled in a proper Git repo. One should do something like git clone https://github.com/frno7/iopmod.git, and then cd iopmod followed by git checkout -b gamepad origin/gamepad. The file tool/version.c is generated using Git and its tags. Hence, if the code isn’t in a Git repo, this won’t work.

The code could be made to be compilable without a Git repo too, of course, but I haven’t done that yet.

The generated version.c is used for the --version tool option.

@Arch91
Copy link

Arch91 commented Jan 22, 2022

Alright, gamepad.irx is compiled.
To test the gamepad driver I compiled «joypadlib-0.14», there is a «main» gamepad test program. However, to compile that, I had to copy the old headers like pad.h (and etc. — ee.h, gs.h, ...) to cross-compiler’s_directory/include/linux/ps2/ . Also I sured that there are ps2pad00 and ps2pad10 device nodes in /dev/ directory. modprobe gamepad goes well. And when I launch that "main" test program, nothing happens. Analog button is not working. After the "main" program is launched, the gamepad's led was originally enlighten, and with the current gamepad driver nothing of that is happening. @frno7, are you trying to make a usual linux gamepad controller driver? Will be the old original PS2Linux device access supported for such programs/libs like joypadlib? If not, will be that result linux gamepad driver support the buttons pressure detection and the vibration functions?

@frno7
Copy link
Owner Author

frno7 commented Jan 22, 2022

@Arch91, could you try the evtest tool as explained on the controller wiki page? It should be very easy to compile, and it’s the best starting point. I believe /dev/input/event# is the modern input device interface for Linux 5.x kernels, and I believe it supports all items listed including motor (rumble) control which would be advertised as FF_RUMBLE when implemented. Modern Linux games use this for most if not all architectures.

Have you taken a look at the official Linux gamepad specification?

@Arch91
Copy link

Arch91 commented Jan 22, 2022

I took a look at the linux gamepad specification, and I see no the detector of how hardly the button is pressed. That's unique for all of the DS>=2 gamepads. Well... I didn't see a worth implementation for that function... only L2/R2 in the race games... Anyway, I do not see how that unique feature is achievable through the standard linux gamepad functions.
Tested evtest. It detected PS2 gamepad1 (connected to the right gamepad slot) in /dev/input/event4 and gamepad2 (to the left gamepad slot) in /dev/input/event5 - are these slots/detection correct? - not vice versa?
Working buttons are the arrows, x,o,^,[], L1/2, R1/2. DS1 is also working, same buttons acceptable.
I see that in the places where that unique pressing function will be needed, it will has to be implemented manually in the source code of that program. Even I could implement the functions of the old joypadlib to PicoDrive-SDL making it working with the gamepads and with their vibration units :D So this birthed that question - is there a chance that there will be two drivers - your new one and an ps2linux'es old renewed one (with pad.h, /dev/ps2pad00/10)?

@frno7
Copy link
Owner Author

frno7 commented Jan 22, 2022

Thanks, @Arch91! I’ve added a new item about pressure sensitivity

  • recognise 256 pressure levels for all buttons except for the analog mode, start, select, L3 and R3;

to the plan. It remains to be investigated how to do that properly though...

Tested evtest. It detected PS2 gamepad1 (connected to the right gamepad slot) in /dev/input/event4 and gamepad2 (to the left gamepad slot) in /dev/input/event5 - are these slots/detection correct? - not vice versa?

I believe that /dev/input/event# devices are dynamically assigned, and therefore have arbitrary numbers starting at 0. First come, first served, I’d guess. The event device description text should tell which controller port it really is, though.

Working buttons are the arrows, x,o,^,[], L1/2, R1/2. DS1 is also working, same buttons acceptable.

Hooray!

I see that in the places where that unique pressing function will be needed, it will has to be implemented manually in the source code of that program. Even I could implement the functions of the old joypadlib to PicoDrive-SDL making it working with the gamepads and with their vibration units :D So this birthed that question - is there a chance that there will be two drivers - your new one and an ps2linux'es old renewed one (with pad.h, /dev/ps2pad00/10)?

Someone could certainly do it, but my focus is on completing the modern /dev/input/event# controller thing. 😄

@mirh
Copy link

mirh commented Jan 22, 2022

https://bugzilla.kernel.org/show_bug.cgi?id=195643

@frno7
Copy link
Owner Author

frno7 commented Jan 23, 2022

@mirh, have you heard anything since its last message on 27 July 2018?

It’s very unfortunate that firms “deprecate” Linux kernel features of hardware they believe are no longer used. The fbdev replacement DRM, for example, is a poor match for the Graphics Synthesizer because it doesn’t work like recent graphics cards, having no EDID etc.

@mirh
Copy link

mirh commented Jan 23, 2022

Not really, but you can chime in.
I guess it's awful when it's just a random noob passing by with handwaved ideas (to this day I'm still not sure evdev is really the system you'd want and need to tinker with), and not somebody that could actually contribute with some code pitch.
Supposedly you should be able to do it with hidapi, but putting aside I have never really checked, I don't know, it still seems a bit too low level than it should.

As for fbdev, it's not that bad either.
https://lwn.net/Articles/881827/
https://www.phoronix.com/scan.php?page=news_item&px=Linux-FBDEV-2022-Maintainer

@frno7
Copy link
Owner Author

frno7 commented Jan 23, 2022

@mirh, my impression is that evdev is the most appropriate controller interface for most applications such as games that needn’t deal with much hardware specifics. For example, everything that broadly looks like a gamepad would work. Presumably hundreds of different makes and models. Sure, USB and Bluetooth devices, possibly via some hidapi library, could be made to work without too much effort in special cases, especially for a limited set of controllers such as the DualShock series and third-party USB adapters for DualShock 2, etc. Emulators would be as good as they could possibly get, given the hardware.

That said, the DualShock 2 is a native device on actual PlayStation 2 hardware, so it’s neither USB nor Bluetooth and hidapi therefore doesn’t apply. The only reasonable alternative I could think of is the special ps2pad device used with Linux 2.x, as suggested by @Arch91, which would require special support with games and libraries such as the SDL. Of course, one could support both evdev and ps2pad devices.

Curiously, netevent is a tool whereby actual PlayStation 2 hardware with DualShock 2 devices attached can share its controllers with another machine, such as PC. No need for silly DualShock 2 USB adapters. 😄

I heard about a new fbdev maintainer, but I assume that the fbdev ban still stands, because fbdev seems to be destined for removal regardless. Once fbdev is disposed, perhaps someone will step up and fix the most pressing problems with the DRM.

@mirh
Copy link

mirh commented Feb 1, 2022

Right, this is about having (and controlling at the source) a driver, not just whatever plain user api.
https://web.archive.org/web/20031229164058/http://playstation2-linux.com/projects/joypadlib
https://github.com/rickgaiser/linux-2.4.17-ps2/blob/master/drivers/ps2/pad.c
Idk really how much of those design decisions could still apply neatly in 2022 then, though I feel like whatever the answer should come to encompass neatly the DS3 too (since its feature set is a strict superset).

Maybe @jonnygrant and @nedelman have still some idea :)
p.s. a multitap driver did exist in the past

@frno7
Copy link
Owner Author

frno7 commented Feb 1, 2022

Right, this is about having (and controlling at the source) a driver, not just whatever plain user api.
https://web.archive.org/web/20031229164058/http://playstation2-linux.com/projects/joypadlib
https://github.com/rickgaiser/linux-2.4.17-ps2/blob/master/drivers/ps2/pad.c
p.s. a multitap driver did exist in the past

@mirh, I’m quite sure they used a Sony gamepad IRX module, and possibly the BIOS. Neither are usable with the controller driver implemented here, since it operates directly on the hardware registers for maximum flexibility, efficiency and performance. I’ve found the following resources usable:

https://problemkaputt.de/psx-spx.htm
https://store.curiousinventor.com/guides/PS2

And helpful notes by Wisi, as mentioned in #22 (comment). Quite a few hardware registers in sio2.h remain to be understood, named, and documented, though.

@Arch91
Copy link

Arch91 commented May 16, 2022

@frno7, I noticed some gamepad related changes made 5 days ago) Share that's new!)

@frno7
Copy link
Owner Author

frno7 commented May 17, 2022

@Arch91, oh? Well, the DualShock was recently mentioned in discussion #75 if you should care to dip into real console games...

@frno7
Copy link
Owner Author

frno7 commented Dec 29, 2022

The Dual Shock gamepad module commit frno7/iopmod@3c9d92e is now on the iopmod main branch. Load it into the kernel with modprobe gamepad. evtest is perhaps the simplest tool to test it, as mentioned in #22 (comment).

@Arch91
Copy link

Arch91 commented Dec 29, 2022

@frno7, so you decided to make the .irx module for the DS®2 gamepads instead of the kernel's module.o... Will you reveal the stormy clouds of your idea why did you do that?)

@frno7
Copy link
Owner Author

frno7 commented Dec 29, 2022

@frno7, so you decided to make the .irx module for the DS®2 gamepads instead of the kernel's module.o... Will you reveal the stormy clouds of your idea why did you do that?)

There’s a lib/firmware/ps2/gamepad.irx for the IOP and its SIO2 hardware, and a lib/modules/*/kernel/drivers/ps2/gamepad.ko for the Linux kernel. The latter loads the former automatically. Both are needed for Dual Shock gamepads to function.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request help wanted Extra attention is needed
Projects
None yet
Development

No branches or pull requests

6 participants