atmega8+V-USB to emulate PS3 joypad

General discussions about V-USB, our firmware-only implementation of a low speed USB device on Atmel's AVR microcontrollers
CRP

atmega8+V-USB to emulate PS3 joypad

Post by CRP » Tue Jan 25, 2011 12:24 pm

Hi, I am currently trying to build a PS2 to USB adapter in order to use PS2 controllers on a PS3. One special feature of PS3 controllers is the "PS" button, which is missing on ordinary PS2 controllers. On a PC, it appears that pressing the PS button of a PS3 controller connected via USB corresponds to button 13, but this does not work when implemented on the atmega8.

I found the following information on the internet:
It’s no secret the PS3 will work with most USB HID gamepads or joysticks. However the Home button is something special. If you connect your sixaxis controller to your PC and monitor button presses, the Home button comes up as button number 13. If you then create a standard gamepad with the same button mapping, the PS3 will refuse to recognize the Home button.

After some tracing of the USB traffic from an official Madcatz Street Fighter IV FightStick I was able to come up with a solution! There are 8 bytes transfered during the enumeration phase, just after the device sends it’s report descriptor. Mimicking the same exchange results in the Home button functioning correctly when button 13 is pressed.


and then:
I think the only problem with the V-USB is that the interrupt pipe can only send out 8 bytes of data at once for low speed device while the full speed device can send more data. For this device, it’s over 8 bytes for sure.


wow! I was testing my code with the V-USB using an atmega88. I was able to use the Home button using your magic bytes! turns out you can stack the interrupt end point to send 19 bytes at once.


Unfortunately I was unable to contact the original poster, so I was wondering if someone can help me in figuring out what the above means, and how I can replicate what he has done in my project.

Thanks
Christian

ulao
Rank 4
Rank 4
Posts: 481
Joined: Mon Aug 25, 2008 8:45 pm

Re: atmega8+V-USB to emulate PS3 joypad

Post by ulao » Wed Jan 26, 2011 3:19 am

Do you know I guy named toodles ? He is the best guy in that department you will find. I know fort a fact he was the first to crack that stupid home button mystery.

CRP

Re: atmega8+V-USB to emulate PS3 joypad

Post by CRP » Wed Jan 26, 2011 1:43 pm

Thanks, I will try and contact him. Meanwhile, does anyone know what " stack the interrupt end point to send 19 bytes at once." means in the context of V-USB?
I am familiar with setting up a report descriptor, and then filling the report with the data that I want the controller to send via USB to the HID driver. I am just not sure what the above phrase means. Would it just mean setting up a section in the descriptor long 19 bytes, and then filling them with those "magic bytes" the ps3 is expecting?

CRP

Re: atmega8+V-USB to emulate PS3 joypad

Post by CRP » Sat Jan 29, 2011 1:01 am

Apparently, to be able to emulate the PS button on PS3, the following has to be done:

Code: Select all

/*
 * Series of bytes that appear in control packets right after the HID
 * descriptor is sent to the host. They where discovered by tracing output
 * from a Madcatz SF4 Joystick. Sending these bytes makes the PS button work.
 */
static uint8_t PROGMEM magic_init_bytes[] = {
   0x21, 0x26, 0x01, 0x07, 0x00, 0x00, 0x00, 0x00
};


So how would I do that in V-USB? Do I need to define usbFunctionRead and change usbFunctionSetup? Or do I just somehow (how?) send those bytes after usbInit?

ulao
Rank 4
Rank 4
Posts: 481
Joined: Mon Aug 25, 2008 8:45 pm

Re: atmega8+V-USB to emulate PS3 joypad

Post by ulao » Sat Jan 29, 2011 2:31 am

I believe its referring to this.

while (!usbInterruptIsReady()) usbPoll(); usbSetInterrupt((void *)&reportBuffer + 0, 8);//send a full byte
while (!usbInterruptIsReady()) usbPoll(); usbSetInterrupt((void *)&reportBuffer + 8, 5); //send 5 more.

You can stack as many as you like but its important to note v-usb will only allow an 8 bit at once. As long as the host is not expecting more then 8 ( like the xbox ) then your ok. If you need more you will gave to modify the source. Myself ands IvIePhisto figured it out here
viewtopic.php?f=8&t=4776&p=16050#p16050
I'm 99.9% sure the ps3 uses a normal 8 bit pipe, where as the xbox uses a mangled version of it thus making it hard to talk to.

CRP
Posts: 7
Joined: Sat Jan 29, 2011 1:09 am

Re: atmega8+V-USB to emulate PS3 joypad

Post by CRP » Sat Jan 29, 2011 9:37 am

Thanks, I got that part working. Unfortunately the whole hid descriptor for the PS3 is much longer than the 31 bytes that according to Christian can be handled by v-usb. Or do you think that by using your patch to send more than 8 bytes per interrupt I can send more than a total of 31 bytes to the PS3? For now I am just using the first 10 bytes of the descriptor, which works for most things but does not allow access to analog shoulder buttons.

Also, do you have any suggestion about those magic bytes to activate the PS button that I mentioned above?

Many thanks for your help and your many useful posts!

ulao
Rank 4
Rank 4
Posts: 481
Joined: Mon Aug 25, 2008 8:45 pm

Re: atmega8+V-USB to emulate PS3 joypad

Post by ulao » Sat Jan 29, 2011 3:43 pm

I pretty much answered these questions for you.

Also, do you have any suggestion about those magic bytes to activate the PS button that I mentioned above?
I know for a fact that Toddles is the only guy that has ever done it. If anyone else has, they copping from him. His project is open source, so just see how he did it.

do you think that by using your patch to send more than 8 bytes per interrupt I can send more than a total of 31 bytes to the PS3
I'm 99.9% sure you can just stack it.

while (!usbInterruptIsReady()) usbPoll(); usbSetInterrupt((void *)&reportBuffer + 0, 8 );//8
while (!usbInterruptIsReady()) usbPoll(); usbSetInterrupt((void *)&reportBuffer + 8, 8 ); //16
while (!usbInterruptIsReady()) usbPoll(); usbSetInterrupt((void *)&reportBuffer + 16, 8 );//24
while (!usbInterruptIsReady()) usbPoll(); usbSetInterrupt((void *)&reportBuffer + 24, 8 ); //32

That ps3 does not use a fancy host like the xbox, I here normal usb device work on it. I really dont know, but I'm positive the controller is a low speed device. If it is a high speed device and send more the 8 at once, then you need my patch. Do your home work, I'm sure the answer is out there.
Last edited by ulao on Sat Jan 29, 2011 9:08 pm, edited 1 time in total.

CRP
Posts: 7
Joined: Sat Jan 29, 2011 1:09 am

Re: atmega8+V-USB to emulate PS3 joypad

Post by CRP » Sat Jan 29, 2011 4:33 pm

Toodles' source is apparently not available, since the site hosting it is down. I found another guy who was able to solve the problem (he used a Teensy board as interface), and the brief source code about the magic bytes that I posted above is from him. Being new at both USB and V-USB, though, my question was really how I can send those magic bytes within the V-USB framework. He says the bytes should be sent right after the HID descriptor, but I do not understand yet where that happens. And once that happens, do I send the bytes per interrupt somehow or do I need to set up a read function?

About the long PS3 descriptor: the full PS3 descriptor is about 282 bytes long, but on a different post on this board, V-USB's developer mentioned that one should not be able to send more than 31 bytes, even stacking them 8 bytes at a time. So my actual question was: does you patch only change the maximum amount of bytes that can be sent on a single call, or does it also raise the total number of bytes that can be sent per interrupt?

In other words, if I use only the first 20-30 bytes of the descriptor, then I am able to send them by stacking as in your example. This would clearly not be possible if I use all 282 bytes. If your patch removes all these obstacles, then I might send the 282 report in a few 32 byte batches.

Thanks again
Chris

ulao
Rank 4
Rank 4
Posts: 481
Joined: Mon Aug 25, 2008 8:45 pm

Re: atmega8+V-USB to emulate PS3 joypad

Post by ulao » Sat Jan 29, 2011 9:08 pm

does you patch only change the maximum amount of bytes that can be sent on a single call
Yes. But if you do the math its possible to make it work for you. With the patch you can send 32 all at once.

I have not heard about a 31 cap, but I know Christian knows his stuff. Not sure what the patch would do I never hit 32 bytes.

ulao
Rank 4
Rank 4
Posts: 481
Joined: Mon Aug 25, 2008 8:45 pm

Re: atmega8+V-USB to emulate PS3 joypad

Post by ulao » Wed Feb 09, 2011 4:10 pm

Well according to what you found have you tried this?

Code: Select all

while (!usbInterruptIsReady()) usbPoll(); usbSetInterrupt((void *)&reportBuffer + 0, 8 );//8
while (!usbInterruptIsReady()) usbPoll(); usbSetInterrupt((void *)&magic_init_bytes+ 8, 8 ); //16


My info shows this...
Here is the order.
0 - report id? Constant 0x01
1 - unknown - constant 0x00
2 - digital bits (Dpad) LDRU Start R3 L3 Select
3 - digital bits square x circle triangle R1(?) L1 R2 L2
4 - digital bits LSB is 'home' button. rest are unknown (byte is 0x01 if home pressed, 0x00 otherwise)
5 - unknown - constant 0x00
6 - left analog X axis - unsigned left low(0x00), right high(0xFF), center 0x80
7 - left analog Y axis - unsigned up low(0x00), down high(0xFF), center 0x80
8 - right analog X axis - unsigned left low(0x00), right high(0xFF), center 0x80
9 - right analog Y axis - unsigned up low(0x00), down high(0xFF), center 0x80
10, 11, 12, 13 - unknown - constant 0x00

the 14 and on up are pressure.

So I think you want to make the home button in the report.
reportBuffer [4]=0b00010000;//ps home pressed. ( or 0b00000000 ) not pressed
while (!usbInterruptIsReady()) usbPoll(); usbSetInterrupt((void *)&reportBuffer + 0, 8 );//8
while (!usbInterruptIsReady()) usbPoll(); usbSetInterrupt((void *)&reportBuffer + 8, 8 ); //16

I also think this depends on your report descriptor. Because my reports 9 and 10 activate the buttons, where this source uses 3 and 4. So In my case I would use report 11 to send the home button.

CRP
Posts: 7
Joined: Sat Jan 29, 2011 1:09 am

Re: atmega8+V-USB to emulate PS3 joypad

Post by CRP » Wed Feb 09, 2011 7:46 pm

In the meantime I have looked a bit at the work done by Mephisto & co (Project Dualstrike). Basically with the patch that they have applied to the usb driver (what this patch actually does is beyond me), they apparently are able to send a 16 byte long hid descriptor in one go. I have tried taking their code and sending longer descriptors, but it won't work. So right now I have adapted the hid descriptor to my needs in order to have all the controls I need, and I barely made it ;)

Basically, according to my limited understanding of the whole issue, in order to get the PS3 to recognize a controller as if it was an official one (which means working PS button and working analog buttons) the following must be satisfied:
1) the hid descriptor must include 13 buttons, one hat switch, 2 analog sticks (2 axes each), 12 analog buttons (these are via the weird custom items at the end of the hid report descriptor)
2) the report must be sent in a single try (ie it is impossible with stock v-usb, which allows max 8 bytes per interrupt; the trick of stacking them will not work, in the sense that by doing so the controller is recognized by the PS3, but the PS button and analog buttons will not work); here mephisto's patch comes into play, since it allows to send up to 16 bytes on interrupt endpoint 3 (can this be extended to more than 16 bytes? I have been unable to do so)
3) the usual magic bytes (0x21, 0x26,...) must be sent via the setup function

In my case, I was able to make a NegCon adapter with the following hid content:
1 byte for left stick axis (wheel)
3 x 2 bits for the remaining three axes (which are unused but must be present)
1 x 4 bits for the hat switch
13 x 1 bits for the digital buttons (button 13 is PS)
1 padding bit ;)
12 x 8 bytes for the analog buttons (the last two are L2 and R2 trigger buttons, mapped to NegCon L and I-II)

So that's exactly 16 bytes and works perfectly ;)

ulao
Rank 4
Rank 4
Posts: 481
Joined: Mon Aug 25, 2008 8:45 pm

Re: atmega8+V-USB to emulate PS3 joypad

Post by ulao » Wed Feb 09, 2011 9:46 pm

Yeah Mephisto was the guy that made the asm patch.

I'm able to do this with out the patch? the ps3 accepts a stacked packet from me.

Glad you got it to work.

CRP
Posts: 7
Joined: Sat Jan 29, 2011 1:09 am

Re: atmega8+V-USB to emulate PS3 joypad

Post by CRP » Wed Feb 09, 2011 11:13 pm

But if you send stacked packets to the ps3, are you also able to use ps home button and analog buttons?
In my experience this does not work and the controller is recognized as a generic joypad by the console.

ulao
Rank 4
Rank 4
Posts: 481
Joined: Mon Aug 25, 2008 8:45 pm

Re: atmega8+V-USB to emulate PS3 joypad

Post by ulao » Thu Feb 10, 2011 2:37 am

Ah I see. Not sure I have not got that far. but I had the same issue with the XBOX and needed that asm patch , so I will find out soon.

Have you tried messing with the device descriptor? When I was working with the xbox this worked on the XBCD driver. I just told windows I was a full speed device and that did the trick. Though to full the actual system I had to report as true full speed device ( more the 8 bytes in one go ). I may try this if I ever get me hands on a ps3.

I dont know if Christian ( author ) ever reads these topics, but if you do read them Christian. I think this would be a cool feature for v-usb. Perhaps a bit out of scoop, but none the less handy.

CRP
Posts: 7
Joined: Sat Jan 29, 2011 1:09 am

Re: atmega8+V-USB to emulate PS3 joypad

Post by CRP » Thu Feb 10, 2011 2:44 pm

I'm afraid my knowledge of the USB protocol is very limited. I have tried messing *a lot* with the hid descriptor, but the only way to get things to work was by using the patched sources and keeping report under 16 bytes. No idea as of now about what I could change in the device descriptor.

So if I understand your mail correctly, using the patch and sending more than 8 bytes in a single interrupt fools the ps3 into thinking that it is dealing with a full speed device.
On the other hand, by looping interrupts and sending a large report in multiple 8 byte chunks allows the use of more complex descriptors, but the host will know this is a low speed device, which implicates that the PS3 does not activate those "proprietary features"

Post Reply