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

Reducing the clock/current apparently makes it not work on USB 3.0 #43

Open
jacksonbenete opened this issue Jan 28, 2022 · 16 comments
Open

Comments

@jacksonbenete
Copy link

So, there are a couple of issues apparently describing the same problem.

I only have USB 3.0 ports available (M1 Air), so I can't test it on USB 2.0.
Considering another issue #30 suggests it work on 2.0 but not on 3.0, I think this might be the case for me as well.
Issues like #41 #34 and maybe #29 , all describe something about the controller getting recognised, but not accepting any inputs as a dead controller or something.

I've spotted that, when I open the apk, and connect the usb, it recognises the "controller" in the system as "PS Vita", this one will appear on softwares as a valid usb controller.

psvita1

psvita2

After some seconds, it will lose the connection and the controller is not "connected" anymore.
Then, the operational system will recognise the usb input with a different name "PS Vita Type B", this one doesn't show on software as a valid usb controller.

psvitatypeb

Even if I unblock the screen, it's still Type B.
(Should unblocking the screen increases the clock and current? This might invalidate my assumptions about the problem)

The difference the OS shows between the two is that:

PS Vita, as a valid input usb have

Current Available (mA):	500
Current Required (mA): 500

PS Vita Type B, not a valid input usb:

Current Available (mA):	500
Current Required (mA): 2

So, maybe that's because USB 3.0 needs more current to work?
I never modded PSVita and my C programming is rust (if it was any good ever), but I would like to try to change something and make it work. I don't know though if I can compile Vita SDK on M1, but I'll try that later.

Any tips about it? Does it sounds reasonable that this might be the problem (current) on USB 3.0?
Maybe the fix is not reduce the clock?

(In the images it shows USB2.0 Hub but it's in fact a hub of USB 3)

Features:
When the VPK is activated, it reduces the clock frequencies to reduce power consumption
@jacksonbenete
Copy link
Author

I'm trying to compile the project but I receive this error on the linking step:

root@5e3a9eb1758f:/build/vitastick/vpk# make
[ 14%] Linking C executable vitastick
/usr/local/vitasdk/bin/../lib/gcc/arm-vita-eabi/10.3.0/../../../../arm-vita-eabi/bin/ld: cannot find -lvitastick_stub
collect2: error: ld returned 1 exit status
make[2]: *** [CMakeFiles/vitastick.dir/build.make:99: vitastick] Error 1
make[1]: *** [CMakeFiles/Makefile2:110: CMakeFiles/vitastick.dir/all] Error 2
make: *** [Makefile:84: all] Error 2

I can run cmake without problems and I can compile the vitasdk/samples.

I'm trying to compile the project as is before trying to compile my proposed changes on the issue.
I'm running the latest vitasdk inside a debian container, the Dockerfile:

FROM debian:buster

env VITASDK /usr/local/vitasdk
env PATH ${PATH}:${VITASDK}/bin

WORKDIR /build

# Install core dependencies for Vita SDK
RUN apt-get update && \
    apt-get install -y sudo wget curl make git-core cmake xz-utils bzip2 python

# Install Vita SDK
RUN git clone https://github.com/vitasdk/vdpm && \
    cd vdpm && \
    ./bootstrap-vitasdk.sh && \
    ./install-all.sh

I can successfully compile the hello_world sample and run it on my PSVita.
I'll be trying to compile the other samples as well but considering that cmake doesn't fail compiling samples, I would guess that it's something else.

@xerpi @rafaelsamenezes @nkrapivin
Do you know what might be causing this cannot find -lvitastick_stub error?
Maybe some of you have faced it before?

@xerpi
Copy link
Owner

xerpi commented Jan 29, 2022

I'm trying to compile the project but I receive this error on the linking step:

root@5e3a9eb1758f:/build/vitastick/vpk# make
[ 14%] Linking C executable vitastick
/usr/local/vitasdk/bin/../lib/gcc/arm-vita-eabi/10.3.0/../../../../arm-vita-eabi/bin/ld: cannot find -lvitastick_stub
collect2: error: ld returned 1 exit status
make[2]: *** [CMakeFiles/vitastick.dir/build.make:99: vitastick] Error 1
make[1]: *** [CMakeFiles/Makefile2:110: CMakeFiles/vitastick.dir/all] Error 2
make: *** [Makefile:84: all] Error 2

I can run cmake without problems and I can compile the vitasdk/samples.

I'm trying to compile the project as is before trying to compile my proposed changes on the issue. I'm running the latest vitasdk inside a debian container, the Dockerfile:

FROM debian:buster

env VITASDK /usr/local/vitasdk
env PATH ${PATH}:${VITASDK}/bin

WORKDIR /build

# Install core dependencies for Vita SDK
RUN apt-get update && \
    apt-get install -y sudo wget curl make git-core cmake xz-utils bzip2 python

# Install Vita SDK
RUN git clone https://github.com/vitasdk/vdpm && \
    cd vdpm && \
    ./bootstrap-vitasdk.sh && \
    ./install-all.sh

I can successfully compile the hello_world sample and run it on my PSVita. I'll be trying to compile the other samples as well but considering that cmake doesn't fail compiling samples, I would guess that it's something else.

@xerpi @rafaelsamenezes @nkrapivin Do you know what might be causing this cannot find -lvitastick_stub error? Maybe some of you have faced it before?

Try building the skprx directory first. This will generate libvitastick_stub.a.

@jacksonbenete
Copy link
Author

Thank you for your reply, and sorry to direct mention you.

TL;DR: I don't know why it doesn't work, but sometimes it does...

Try building the skprx directory first. This will generate libvitastick_stub.a.

That's correct, building the skprx directory generates the libvitastick_stub.a, which I had to copy/move manually to the vpk directory because the make apparently will look for the file on the current directory and will not try a "../skprx/".

I also noticed that I had to copy the vitastick.skprx I generated and overwrite the old file that was already in there.

  • Using the github release vitastick.skprx with the github release of vitastick.vpk will open the app on PSVita.
  • Trying to use the github skprx with my compiled vpk crashed the app on PSVita.
  • Trying to use my own skprx with my own vpk will open the app on PSVita.

I wasn't expecting that, considering that I didn't changed anything inside the skprx folder, maybe there is some kind of hash generated and the app will detect that it wasn't compiled together?

Anyways, after learning those two lessons, I managed to compile my version of the vpk and run it.
It worked (kinda), but not because of my assumptions.

As you can see it successfully detected the Vita and I could map the buttons.
(Button 16, Button 15...)

Screenshot 2022-01-29 at 18 38 46

It also worked on a Steam application (Blasphemous).

Screenshot 2022-01-29 at 19 30 51

(Interesting that the applications detect different buttons, Square is Button 0 for the Emulator, but it's Button 1 for Blasphemous)

Now, as I've said, it "kinda" worked.
That's because it doesn't always works, and that's how I understood that my assumptions about current and clock aren't correct.

I've implemented two routines for increasing and decreasing the clock inside the application.
It doesn't make difference, if the app is working it will keep working, and if it doesn't, increasing the clock doesn't make it work.

I noticed that if I reboot the PSVita, if vitastick is the first application I open after rebooting, it have more chances to work.
Now, how I know that?
Not only because I closed and reopened the application, and rebooted the console multiple times testing, but I've implemented a routine for "SELECT+TRIANGLE", all it does is stop vitastick and start it again (without closing the app).

// reload app
if ((pad.buttons & reload_vitastick_mask) == reload_vitastick_mask)
{
  printf("\nrestarting vitastick...\n");
  vitastick_stop();
  ret = vitastick_start();  
  if (ret >= 0) printf("vitastick restarted successfully!\n");
}
  • if I close the application with "SELECT+START" and open it again it'll not work until a reboot.
  • if I "restart" with my routine it'll stop woking as well, need reboot.
  • if I unplug and plug the usb again, need reboot...
  • if the controller is working and I lock the screen, need reboot.

Sometimes I have to reboot multiple times using VitaShell for it to work again.

For a moment I thought that maybe my USB cable was broken or something, but the idea was exactly to select+triangle to stop and start the application again without touching the cables.

What happens is that, every time I say it "doesn't work" it do shows the "PS Vita" as input, but trying to map the buttons on emulator or game doesn't work.

Only once I did a "select+triangle" and the controller started working.

So it's completely random.
I don't know what else to try, but it was fun trying...

@xerpi
Copy link
Owner

xerpi commented Jan 29, 2022

@jacksonbenete Nice experimentation you've been doing here!
I think the problem is that PSVita's OS (actually the LiveArea) always tries to activate the MTP driver. It seems the way USB is implemented on the Vita doesn't really allow to easily switch between drivers easily and reliably, so vitastick tries to unload all the lower level UDCD drivers and then load all of them but instead of activating the MTP driver it activates vitastick: https://github.com/xerpi/vitastick/blob/master/skprx/main.c#L405
Maybe placing ksceKernelDelayThread between ksceUdcdStart could help?
Probably somebody on this server knows better (#vita-dev channel).

@xerpi
Copy link
Owner

xerpi commented Jan 29, 2022

Regarding the current (mA), can you try playing with the bMaxPower (there are 2 places) here? Now it's 0, try setting it to 1 (it would mean 2mA).

bMaxPower defines the maximum power the device will drain from the bus. This is in 2mA units, thus a maximum of approximately 500mA can be specified. The specification allows a high powered bus powered device to drain no more than 500mA from Vbus. If a device loses external power, then it must not drain more than indicated in bMaxPower. It should fail any operation it cannot perform without external power.

The bmAttributes field could also be helpful. Right now it's 0xC0 (which is 11000000 in binary, so bits 6 and 7 are set).

bmAttributes specify power parameters for the configuration. If a device is self powered, it sets D6. Bit D7 was used in USB 1.0 to indicate a bus powered device, but this is now done by bMaxPower. If a device uses any power from the bus, whether it be as a bus powered device or as a self powered device, it must report its power consumption in bMaxPower. Devices can also support remote wakeup which allows the device to wake up the host when the host is in suspend.

More info here: https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/usbspec/ns-usbspec-_usb_configuration_descriptor

@mswlandi
Copy link

mswlandi commented Feb 2, 2022

hi guys, hope you're doing well.

I've been experimenting to find a solution to the "controller being recognized but not sending inputs" problem, that normally occurs after the first run of vitastick.

I've made vitakeyboard based on hidmouse and vitastick, and like hidmouse, it doesn't have that problem for some reason, so I'm trying to replicate a few things from vitakeyboard to see what is causing it.

when using lsusb the device is listed with product ID 1337 as expected, but when using something like usbhid-dump -d 054c:1337 -e all to see the reports, I can see that nothing is actually sent. I've tried some things with no success:

  • taking out the EventFlag logic and replacing it for a simple check of ksceUdcdGetDeviceState and delay of the thread on the USB thread loop, like done in hidmouse
  • calling vitastick_stop before vitastick_start (this would only solve if for some reason the app was closing without vitastick_stop being called, which is not the case for the select+start combo)
  • some other useless stuff like using int state = 0; instead of unsigned long state; for the SYSCALL stuff

anyway, gonna keep trying... If you have any ideas I can try them out
@xerpi I haven't tried placing ksceKernelDelayThread between the ksceUdcdStart or changing current yet (cause I don't think those are the cause) but I can try later

also, for some reason I can't get LOG to work, even though it was working when I copied it for vitakeyboard 🤔

@jacksonbenete
Copy link
Author

hi guys, hope you're doing well.

I've been experimenting to find a solution to the "controller being recognized but not sending inputs" problem, that normally occurs after the first run of vitastick.

I've made vitakeyboard based on hidmouse and vitastick, and like hidmouse, it doesn't have that problem for some reason, so I'm trying to replicate a few things from vitakeyboard to see what is causing it.

when using lsusb the device is listed with product ID 1337 as expected, but when using something like usbhid-dump -d 054c:1337 -e all to see the reports, I can see that nothing is actually sent. I've tried some things with no success:

  • taking out the EventFlag logic and replacing it for a simple check of ksceUdcdGetDeviceState and delay of the thread on the USB thread loop, like done in hidmouse
  • calling vitastick_stop before vitastick_start (this would only solve if for some reason the app was closing without vitastick_stop being called, which is not the case for the select+start combo)
  • some other useless stuff like using int state = 0; instead of unsigned long state; for the SYSCALL stuff

anyway, gonna keep trying... If you have any ideas I can try them out @xerpi I haven't tried placing ksceKernelDelayThread between the ksceUdcdStart or changing current yet (cause I don't think those are the cause) but I can try later

also, for some reason I can't get LOG to work, even though it was working when I copied it for vitakeyboard 🤔

I'm short of time until Friday but I'll later, or this weekend, try to compile an older versions of vitastick.
You forked the hidmouse project from 2017 and it just works right?
Vitastick also exists since 2017, maybe the base code was the same or very similar.

From 2017 to 2021 vitastick received some commits and pull requests, maybe in the way something might have been removed by mistake?

If the 2017 version of vitastick works as expected, we can then backtrack by the commit's diffs to understand what's missing and in what point it stopped sending inputs.

@mswlandi
Copy link

mswlandi commented Feb 5, 2022

Hey I think I figured it out!

When sending reports, both vitastick and hidmouse account for only sending HID reports (the data) when the previous report was sent. vitastick does this with EventFlags (sends a sort of "report sent" event when report is sent and waits for this event before sending a new one) and hidmouse does it with a field of the report structure as a flag that is polled every iteration of the USB thread loop.

But there's other places in the code in which data is sent, that vitastick is not accounting for only sending the next report when the previous one was already sent. That would be:

  • send_hid_report_desc() - when the host asks for the report descriptor, that is, when you connect the USB device and it describes its reports' structure
  • send_hid_report_init(report_id) - if I understand this correctly, after asking for the report descriptor, the host asks for the first report, which should contain the state of the controller in rest state (it works if you don't send this, but xerpi has implemented it)
  • send_string_descriptor(descriptor_idx) - this is called when the system is setting up the name of the controller. For some reason this is not called in my linux mint system, and the controller is named 'SONY "PS Vita"', which I guess is the default name for the ps vita. Because my system doesn't call this, not changing it to account for already sent packets don't break the connection, but a final solution should account for this

I've tested modifying these using the hidmouse solution and it seems to work and never be in that state of "connected but not sending inputs". I'll try implementing it in a simpler way using global variables and make a PR so you guys can test it. I don't think using EventFlag here makes sense since we aren't expected to continuously send this data nor have multiple events that affect a loop, like the main reports do.

@mswlandi
Copy link

mswlandi commented Feb 5, 2022

Okay so global variables don't seem to be working for some reason... Maybe the hidmouse solution of using the unused attribute of the request makes more sense since the on_complete will for sure have access to the pointer to the request (which will contain the unused attribute)

I'll stop working on this for today but here's the branch with the hidmouse solution I'm talking about: https://github.com/mswlandi/vitastick/tree/hidmouse-solution

@jacksonbenete can you try building and testing it to confirm it fixes the bug?

@jacksonbenete
Copy link
Author

Okay so global variables don't seem to be working for some reason... Maybe the hidmouse solution of using the unused attribute of the request makes more sense since the on_complete will for sure have access to the pointer to the request (which will contain the unused attribute)

I'll stop working on this for today but here's the branch with the hidmouse solution I'm talking about: https://github.com/mswlandi/vitastick/tree/hidmouse-solution

@jacksonbenete can you try building and testing it to confirm it fixes the bug?

I've tried both master branch and origin/hidmouse-solution.

It works sometimes when vitastick is the first app I open, then if I close vitastick (select+start) and open it again, it doens't work for me.
Then I have to reboot for it to work again but sometimes it takes multiple reboots.

Does it works for you? Have you tried closing vitastick app and opening it again, it keeps working?

@mswlandi
Copy link

mswlandi commented Feb 5, 2022

I've tried both master branch and origin/hidmouse-solution.

The master branch has no changes in relation to xerpi/vitastick

It works sometimes when vitastick is the first app I open, then if I close vitastick (select+start) and open it again, it doens't work for me. Then I have to reboot for it to work again but sometimes it takes multiple reboots.

Does it works for you? Have you tried closing vitastick app and opening it again, it keeps working?

Huh, yeah it was working for me, no matter how many times I closed the app and reopened again... I'll test it again later. Maybe it was some small change I made in the vpk that I didn't commit

@jacksonbenete
Copy link
Author

It works sometimes when vitastick is the first app I open, then if I close vitastick (select+start) and open it again, it doens't work for me. Then I have to reboot for it to work again but sometimes it takes multiple reboots.
Does it works for you? Have you tried closing vitastick app and opening it again, it keeps working?

Huh, yeah it was working for me, no matter how many times I closed the app and reopened again... I'll test it again later. Maybe it was some small change I made in the vpk that I didn't commit

That's nice. Let me know if there was some commit pending so I'll try it again!

If it's not the case, maybe it's just a bad luck about my device, or might be something between OS, since you're on Linux and I'm on macOS.
Even though macOS is Unix compliant, might be some kernel thing involved, I'm not sure if macOS is good on dealing with joysticks, I think I've heard complains about other controllers/joysticks as well.

@mswlandi
Copy link

mswlandi commented Feb 6, 2022

That's nice. Let me know if there was some commit pending so I'll try it again!

I tested with the original vpk and it indeed wasn't working - it seems that commenting out the clock-changing functions was necessary.
So I did that, and also I wasn't accounting for the string and report descriptors (was only accounting for initial and normal reports).

If you want to test that'd be appreciated (hidmouse-solution branch). If it works I'll continue trying to make a simpler version of the fix that uses global variables or similar.

@jacksonbenete
Copy link
Author

That's nice. Let me know if there was some commit pending so I'll try it again!

I tested with the original vpk and it indeed wasn't working - it seems that commenting out the clock-changing functions was necessary. So I did that, and also I wasn't accounting for the string and report descriptors (was only accounting for initial and normal reports).

If you want to test that'd be appreciated (hidmouse-solution branch). If it works I'll continue trying to make a simpler version of the fix that uses global variables or similar.

So the clock reduction issue did made some difference after all?

Anyway I tested it and it did worked.
Not every time though, but I can say it's way, way better.

Before, it took me multiple reboots to make it to work, and when it finally worked, if I closed the app or disconnected the USB it was all gone and I had to reboot multiple times again for another lucky moment.

Your branch, although sometimes I'll reboot and it'll not work, it does work more often.
Also, closing the app and opening it again will have a better chance to work.
The more successful attempt I could close the app and open it again three times and it kept working, but closing it one more time and opening it again it was not working anymore.
Again I'm not sure if it's a kernel/OS thing or maybe you didn't tested it stubbornly like me lol as I kept closing and opening the app to investigate the behaviour and make sure it wouldn't stop working.

But again, sometimes I'll reboot the device and it'll not work, and sometimes it will work but after one or two times closing the app and opening it again, it'll not work anymore.

We don't have a usbhid-dump in macOS but I've found a supposedly similar project called mac-hid-dump.
When I do a mac-hid-dump |grep -A 6 '1337' I'll get the descriptor:

054C 1337: SONY - "PS Vita"
DESCRIPTOR:
  05  01  09  05  a1  01  a1  00  85  01  05  09  19  01  29  10 
  15  00  25  01  95  10  75  01  81  02  05  01  09  30  09  31 
  09  32  09  33  15  81  25  7f  75  08  95  04  81  02  c0  c0 
  
  (48 bytes)

I'll successfully receive the descriptor doesn't matter if the controller is working or not though, unless I put the Vita to sleep, if I do that the pid will not be found as the device will change for the non-vitastick usb connection.

When I have the time I'll try the suggestion xerpi made about the delay.

In fact I was thinking that we should put the "connection" (vitastick_start) inside the loop (wait_key_press).
I mean the start and all the if statement

That's because apparently it might be losing something from the start routine since the LiveArea might try to recover the usb state as xerpi mentioned, if we can keep the connection alive all the time, meaning we keep checking it's connected, we can instantly try to recover the connection, or restart it.
Maybe it's a problem to "stop" and "start" the controller all the time, of course, but if we write the function to recover the connection only when needed we might be able to keep the connection alive.
Having to "SELECT+START" every time something goes wrong sounds too much trouble, we should be able to make it auto-recover, I mean a self-healing system, what do you think?

I don't know if it's possible to make it this way as I don't understand the Vita OS and kernel, but it's something that have occurred to me, that we have a "main loop" that don't check the application state, only the controller state reading the buttons (sceCtrlReadBufferPositive), we could have more control and power over the application after it started running.
Does it makes sense?


I was just thinking about something else non-related to this issue, I think we can make it to transmit the buttons differently later.
What I mean is, if you connect a proper joystick, you'll often receive buttons as "△", "x", etc. But instead we receive "Button 1", "Button 3", etc.
I didn't take the time to look for it but I think there might be something on the specification of the protocol to send a more recognisable button like an original joystick. That's because some buttons on Vita will map to "Button " and some will map to an icon/symbol, so I guess we could be able to make everything map to a icon/symbol if we know the correct value to transmit.
But that's something I was just thinking, I'll try to get some time to focus on the problem we have in hand and think about this aesthetic enhancement later.

@mswlandi
Copy link

mswlandi commented Feb 8, 2022

or maybe you didn't tested it stubbornly like me lol as I kept closing and opening the app to investigate the behaviour and make sure it wouldn't stop working.

I tested closing and opening up to 10 times (before pushing the commit I think it was 7 times) and it didn't stop working.
As for closing the app with the home button, that would skip vitastick_stop and probably break it until you actually close it with select + start.
That's why there's a commented line in my branch with vitastick_stop() just before vitastick_start(), cause it would make it always work when reopening the app.

But again, sometimes I'll reboot the device and it'll not work, and sometimes it will work but after one or two times closing the app and opening it again, it'll not work anymore.

Huh. Yeah, it might be a difference in the drivers of linux and macOS... I can test in windows later and see what happens.

but if we write the function to recover the connection only when needed we might be able to keep the connection alive. Having to "SELECT+START" every time something goes wrong sounds too much trouble, we should be able to make it auto-recover, I mean a self-healing system, what do you think?

Yeah, that makes sense, it would be smart to check if it is connected every iteration of the loop. That is assuming of course that it is possible, but we can try finding out how

I don't know if it's possible to make it this way as I don't understand the Vita OS and kernel, but it's something that have occurred to me, that we have a "main loop" that don't check the application state, only the controller state reading the buttons (sceCtrlReadBufferPositive), we could have more control and power over the application after it started running. Does it makes sense?

Yeah it makes sense... In fact it makes me think if the problem is that for some reason peaking the controls at the kernel plugin USB loop stops working after a reset... Maybe I could try making it like vitakeyboard: exporting a function to userland so the app can call it to press the buttons

I was just thinking about something else non-related to this issue, I think we can make it to transmit the buttons differently later. What I mean is, if you connect a proper joystick, you'll often receive buttons as "△", "x", etc. But instead we receive "Button 1", "Button 3", etc. I didn't take the time to look for it but I think there might be something on the specification of the protocol to send a more recognisable button like an original joystick.

That's probably because vitastick was made to emulate a generic gamepad device, and so its descriptors make the computer think it's just that, with generic buttons. To make the computer receive triangle and cross for example, we'd probably have to emulate a Dualshock...
I haven't looked too much into that but I suspect that's more difficult due to the proprietary nature of the dualshocks.
If I'd really want to do that I'd look at how the linux drivers recognize a dualshock, to make it recognize the vita as a dualshock and then hope that the other closed source OS's will recognize them in the same way...

@Sneethe
Copy link

Sneethe commented Jun 29, 2022

I guess I'll report my findings...
Using mswlandi fork. Vitastick can be coaxed into functioning. Using gamepad-tester.com reports the controller to be working however with the left and right dpad being inverted and the X O □ buttons being mixed up.
However if the screen is turned off (either by the power button being pressed or inactivity) or the playstation button is pressed, the game controller will become unavailable (USB disconnect according to dmesg) and a restart will be required.

EDIT: Neither using a USB3 nor USB2 port made any difference.

So using this in conjunction with a plugin that stops the screen turning off after inactivity is recommend.
For people who are reading this thread and don't have a vita Development environment. I compiled mswlandi vitastick/hidmouse-solution
vitastick.zip
Note last commit for vitastick.vpk was: a1f80a3

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants