Mega32 as Xb*X gamepad

General discussions about V-USB, our firmware-only implementation of a low speed USB device on Atmel's AVR microcontrollers
ulao
Rank 4
Rank 4
Posts: 481
Joined: Mon Aug 25, 2008 8:45 pm

Re: Mega32 as Xb*X gamepad

Post by ulao » Mon Feb 01, 2010 4:01 am

I put up a lil test-prog without the whole PS2 mouse and keyboard stuff but it won't work either.
Wait are you saying you cant even get examples to work? If so scratch the entire xbox thing for now, and start from the examples. Get a normal HID joystick app working then try to complicate ;)

Grobi
Posts: 6
Joined: Tue Jan 26, 2010 6:55 pm

Re: Mega32 as Xb*X gamepad

Post by Grobi » Tue Mar 30, 2010 5:42 pm

No, the examples (Mouse, Keyboard, Joystick etc.) works like a charm. Only the xbox controller stuff does not work at all, thats why i am interested in your approach for that.

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

Re: Mega32 as Xb*X gamepad

Post by ulao » Sun Apr 11, 2010 12:18 am

Grobi, I was sort of interested in trying this again. After failing to talk to the non-existent descriptor I gave up. But maybe helping you will get me thinking right and finally get this done.

First what is the issue, you can not enumerate it? To me this is the easiest part. I looked back at the code and your device config is wrong. Should be

Code: Select all

   0x12, //size of this descriptor in bytes
   USBDESCR_DEVICE, //descriptor type = XBOXUSB_Device_Descriptor
   0x10, 0x01,    //USB Spec 2.0
   0x00,       //class code
   0x00,      //subclass code
   0x00,      //protocol code
   0x08,      //EPO buffer size ( needs to be 40, but I cant get it to work )
   0x5E, 0x04,   //vendor ID 04D8
   0x89, 0x02, //product ID
   0x21, 0x01, //device release number


    0,          /* manufacturer string index */

    0,          /* product string index */

    0,          /* serial number string index */

    1,          /* number of configurations */


I made a few changes to it myself but both of my versions worked fine. And yes you do not need a report desc. Also I do have two endpoints set up but think that is only for rumble.


UPDATE: Ok I see where your problem is ;) I's shocked no-one caught this.

Code: Select all

 usbSetInterrupt(reportBuffer, sizeof(reportBuffer));
Not going to work... yoy need to use a size no greater then 8.

like

Code: Select all

 usbSetInterrupt(reportBuffer,8;)
Now this is the trick here.. xbox has a report size of 20 ( decimal ) but the packet size is 0x20 ( 32).

So we should send it in 4 sets of 8..

Code: Select all

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


This is where I'm a bit stuck. If I set the report size to 10 I get all buttons working. But no analogs. Using a report of 8 I get flashy button ( wrong size I think ) and the pov works.

If I could send one set of 20 We'd be in good shape but maximum packet size for low-speed peripherals is 8 bytes, for full-speed peripherals it can be 8, 16, 32, or 64 bytes . v-usb also has 0 descriptor masters even Christian ovoids these questions and he really knows his stuff. On another project I needed more then 8 and was able to use two sets of 8, and everything worked out fine.

Code: Select all

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


So this method does work on v-usb.

Problem here is the usb will not enumerate if I use anything greater then 10. Why 10 I dont know..? We also can not use a packet size of 32, but as I showed above we can get over that by sending multiple packets.

I figure this would work.

Code: Select all

  while (!usbInterruptIsReady()) usbPoll();
      usbSetInterrupt((void *)&reportBuffer + 0, 10);
        while (!usbInterruptIsReady()) usbPoll();
      usbSetInterrupt((void *)&reportBuffer + 10,  10);
but I only get buttons the reports 10 and greater are ignored. The interesting thing is I dont get flashy buttons, so the packets are the right size I think?

my last idea what this

Code: Select all

        while (!usbInterruptIsReady()) usbPoll();
      usbSetInterrupt((void *)&reportBuffer + 0, 8);
        while (!usbInterruptIsReady()) usbPoll();
      usbSetInterrupt((void *)&reportBuffer + 8, 8);
         while (!usbInterruptIsReady()) usbPoll();
      usbSetInterrupt((void *)&reportBuffer + 16, 4);
still not right as the report over laps ( flashy buttons ). but here we maintain the packet size limit of 8, and dont go over 32. 8+8+4 totaling in 20. Will a low speed device work? And from what I know v-usb will not do or emulate a full speed deivce.

UPDATE2:

I notice that

Code: Select all

        while (!usbInterruptIsReady()) usbPoll();
      usbSetInterrupt((void *)&reportBuffer + 0, 8);
        while (!usbInterruptIsReady()) usbPoll();
      usbSetInterrupt((void *)&reportBuffer + 8, 4);
Will not cause the report to over lap

but

Code: Select all

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


Seems 10 is all the report will except, yet I know it should be 20. I tried to change the first bit to a 2 hoping it was the report ID, but no luck. Also reportBuffer[1] should be 14, but any other value has 0 effect. This is the report size. Not sure why its variable?

Also, I did try sending 10 and it does actually expect this..

Code: Select all

        while (!usbInterruptIsReady()) usbPoll();
      usbSetInterrupt((void *)&reportBuffer + 0, 10);
I'm able to control the black and white buttons with this. I'm not sure how the v-usb is allowing a report size of 10 out of a 8 max pipe? but it does.. and anything greater kills enumeration as expected.

My only other guess, and this is a long shot is to do this.

Code: Select all

        while (!usbInterruptIsReady()) usbPoll();
      usbSetInterrupt((void *)&reportBuffer + 0, 10);

wait some exact time..     

      usbSetInterrupt((void *)&reportBuffer + 10, 10);


UPDATE3: I just noticed sending in bytes of 10, prevent data from being change after the first send. That is to say, you only get one packet sent, I'm not too surprised since low speed device are designed to work with 8. So scratch all of the "10" examples above they wont work..

will not work..

Code: Select all

        while (!usbInterruptIsReady()) usbPoll();
      usbSetInterrupt((void *)&reportBuffer + 0, 10);


needs to be..

Code: Select all

        while (!usbInterruptIsReady()) usbPoll();
      usbSetInterrupt((void *)&reportBuffer + 0, 8);
And so far I can not send more then one pack..

Grobi
Posts: 6
Joined: Tue Jan 26, 2010 6:55 pm

Re: Mega32 as Xb*X gamepad

Post by Grobi » Tue Apr 13, 2010 8:16 pm

damn, so the overall problem is that the xbox controller is a fullspeed device which v-usb does not support and since v-usb isnt going to support low speed devices with report descriptor greater 8 bytes it will never work.
I think the xbox usb implementation does not care if the controller is a full or low speed device, the descirptor and stuff had to be set up right to make it work.

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

Re: Mega32 as Xb*X gamepad

Post by ulao » Tue Apr 13, 2010 9:46 pm

Well I know my post was lengthy but if you look back you will see I was able to send multiple packets with another project I had. So in theory , this should work. I'm not sure what the bottle neck is. I personally think its my knowledge of v-usb. But getting anyone with the correct knowledge or expertise is like pulling teeth around here.


I strong encourage you to get at the same point I'm at, sometimes two heads are better then one. Currently I can press all buttons but white and black, and the pov d-pads work. Maybe if you get to that point we can figure this out. I still think some v-usb knowledge or feedback is required.

UPDATE:: going to try USB_CFG_LONG_TRANSFERS set to 1, never saw that before... Stay tuned.

Update ok, didnt seem to help, but funny fixed another problem I was having with desc lengths ;) ( unrelated to this topic )

I also saw this "If you need to transfer more bytes, use a control read after the interrupt" What is a control read?

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

Re: Mega32 as Xb*X gamepad

Post by ulao » Fri Jul 02, 2010 10:48 pm

Ok I got! Just needed to put the project a side for a bit ;) Was so simple the entire time, just had to not use bulk transfers , that all!

IvIePhisto
Posts: 14
Joined: Thu Aug 19, 2010 3:04 pm

Re: Mega32 as Xb*X gamepad

Post by IvIePhisto » Thu Aug 19, 2010 3:26 pm

Hi and thanks for discussing this matter, your conversation was of some help to me :D

I'm trying to create a XBox controller on an ATmega168 using V-USB and got to the point where the XBox is getting input, but not all of it. I'm sending the 20bytes of the report through the interrupt in endpoint (either with number 1 or 2, both work) in 3 pakets of 8, 8 and 4 bytes, but all pakets are interpreted by the XBox like it was the whole report. I got some information about the meanings of the bytes of the vendor request 0x06 by trial and error, the most interesting part being that byte 7 has to be greater than 7 and less than or equal the max paket size of the interrupt in endpoint. The result is the same if the max paket size for the interrupt in endpoint is 8 or 32 on XBox, with XBCD it only works if it is 8. You can find the current state in the Dual Strike subversion repository, the most crucial file for XBox support being xbox.c, the desciptors being in descriptors.c (device descriptors, starting at line 263), some more XBox behavior being in usb_controller.c (vendor request 0x06, starting at line 180).

@ulao: How did you get it working? You wrote "just had to not use bulk transfers", but I can't make anything out of it, as you seem to have used interrupt transfers all the time. Do you reply to the vendor request 0x06, and if you do, how? Please enlight me!

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

Re: Mega32 as Xb*X gamepad

Post by ulao » Fri Aug 20, 2010 4:10 am

Hi and thanks for discussing this matter, your conversation was of some help to me
Sure thing that was the point and hope that other would join in.

The reason it will not work is that we need to act as a usb 2,0 device. Fortunately we get recognized. The part I could not get working ( not giving up yet, just on Hiatus ) is sort described here. http://forums.obdev.at/viewtopic.php?f=8&t=4556


If you can help me make that work I can show you how to send the full report.
the Xbox is set up in bulk and we must send more then 8 packets. From what I read we can do this with usbSetInterrupt3... Hop on that thread and give it a go, if you get it to work let me know!

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

Re: Mega32 as Xb*X gamepad

Post by ulao » Mon Aug 23, 2010 11:31 pm

Well as you pointed out
The max packet size limits the maximum data to be transferred in one interrupt transfer request, to send reports greater than 8 it has to be splitted into packets of a maximum size of 8, this works perfectly at least for HID devices on Windows and V-USB XBox controllers with XBCD. Another important thing to note is that in V-USB the report buffer size is 8. I tried modifying it to make it bigger. As I understand it with usbSetIntterupt[3] a buffer is filled and the appropiate interrupt in request buffer is filled as well as it's length set. In one of the next usbPoll calls this data is sent to the host and the buffer set to be sent. What we would have to do is make the buffer bigger (quite easy) AND change the assembler part of V-USB to send packets bigger than 8 (contradicting the standard, but might be working anyways, at least on XBox). I couldn't nail the point down where the interrupt in data is sent, maybe christian could help there.


This is sort of what I feared. I was hopping the usbSetIntterupt[3] would get us around it but I agree its not going to work. I wont be much hep on the ASM side of things. Writing it I can handle debugging it is a nightmare. I truly hope Christian has a few minutes/hours to offer some advice.

Post Reply