Page 1 of 1

usbSetInterrupt3, does it work?

Posted: Mon Jul 05, 2010 5:10 am
by ulao
- One additional interrupt- or bulk-in endpoint. This was endpoint 3 in
previous versions of this driver but can now be configured to any endpoint
number. You must define USB_CFG_HAVE_INTRIN_ENDPOINT3 in order to activate
this feature and call usbSetInterrupt3() to send interrupt/bulk data. The
endpoint number can be set with USB_CFG_EP3_NUMBER.


I have a need for this specifically.
Please note that the USB standard forbids bulk endpoints for low speed devices!
Most operating systems allow them anyway, but the AVR will spend 90% of the CPU
time in the USB interrupt polling for bulk data.

From what I know the host is capable of low and hi speeds. Lots of contradicting info on it. Its set up like so

Code: Select all

#if USB_CFG_HAVE_INTRIN_ENDPOINT    /* endpoint descriptor for endpoint 1 */
    7,          /* sizeof(usbDescrEndpoint) */
    USBDESCR_ENDPOINT,  /* descriptor type = endpoint */
    0x82,       /* IN endpoint number 1 */
    0x03,       /* attrib: Interrupt endpoint */
    32, 0,       /* maximum packet size */
    0x04, /* in ms */

Now its not a computer, but a have a version working on the PC I can test with. I can talk to either just fine with a packet size of 8. Since it is set up in bulk I must send more then 8 packets. Now from what I read I can do this with usbSetInterrupt3. However there are a grand total of one example(s) out there.
http://wayne.klinkerstein.m-faq.de/AVRUSB/Main.c
And this examples not only does not work , confused me as it hijacks 0x22 with SET_CONTROL_LINE_STATE. So its of no use to me, not that its a reputable example anyways. Would be great to see an office V-USB example, or at a minimum one on the examples page.


I tried a few ways to use this ...

#define USB_CFG_EP3_NUMBER 1
#define USB_CFG_HAVE_INTRIN_ENDPOINT3 1

and tried
while (!usbInterruptIsReady3()) usbPoll();
usbSetInterrupt3( XreportBuffer , 8);

Do I need to use usbFunctionSetup to grab the notification? If so how. I tried rq->bRequest == 0x22 ( as suggested in that example ) but nothing caught. Where could I find an example that uses usbSetInterrupt3/usbInterruptIsReady3.

Re: usbSetInterrupt3, does it work?

Posted: Fri Aug 20, 2010 9:51 am
by IvIePhisto
I got it working for the XBox mode of the Dual Strike project. See these files:
  • usbconfig.h
  • descriptors.c, see the XBox part.
  • xbox.c, the data is sent at the bottom with "sendDataUSB3()".
  • usb_controller.c, here "sendDataUSB3()" is declared. It just schedules chunks of 8 bytes (except possibly the last one) of the given data for sending with "usbSetInterrupt3()" until the whole data is processed and waits in between by polling with "while(!usbInterruptIsReady3()) usbPoll();".

I spotted a few things in your post:
0x82, /* IN endpoint number 1 */
The 0x82 means it's an in endpoint (high byte) with number 2, so the comment is wrong (but you maybe knew that ;)).
32, 0, /* maximum packet size */
For me this doesn't work on a PC (Windows 7), supposedly because it contradicts the low-speediness, but a XBox keeps polling for data. If it is 8 it works on PC perfectly.
#define USB_CFG_EP3_NUMBER 1
Should be 2, as this is the number configured.
#define USB_CFG_HAVE_INTRIN_ENDPOINT 1
Do you have this defined? It has to or the code for the other endpoint is not used.

And for your question:
Do I need to use usbFunctionSetup to grab the notification?
I don't use it, so maybe it's not needed ;)
EDIT: After looking a bit more into the code, I suppose it is CDC-related.

Re: usbSetInterrupt3, does it work?

Posted: Fri Aug 20, 2010 8:30 pm
by ulao
It is always nice to know my posts and code has helped others, even better when that person can give back a little ;) thx, can wait to try it out will post my results when I get a chance to try it.

FYI: That code snipit up there is not from my project its from a UPCB project. I just posted it as that is how he did it. So yeah the comments can be wrong. I just needed to make the usbSetInterrupt3 work, and it looks like you did it. OH also I did define that ENDPOINT yes ;)

Re: usbSetInterrupt3, does it work?

Posted: Fri Aug 20, 2010 11:31 pm
by IvIePhisto
I hope you get it working with this information. I know the UPCB and got the XBox vendor request from there, but the XBox won't accept the setup I described :( Looking forward to your answer in the other thread ;)

Re: usbSetInterrupt3, does it work?

Posted: Sat Aug 21, 2010 7:41 pm
by ulao
I took a stab at it, plan to do a bit more when I get a chance. So far I do not see any data coming out of sendDataUSB3. Just so that you see what I'm working with here is my config.

Let me know if you spot anything wrong.

Code: Select all

uchar my_usbDescriptorConfiguration[] = {    /* USB configuration descriptor */
     9,          /* sizeof(usbDescriptorConfiguration): length of descriptor in bytes */
    USBDESCR_CONFIG,    /* descriptor type */
    18 + 7 * USB_CFG_HAVE_INTRIN_ENDPOINT + 7 * USB_CFG_HAVE_INTRIN_ENDPOINT3 + 9, 0,
                /* total length of data returned (including inlined descriptors) */
    1,          /* number of interfaces in this configuration */
    1,          /* index of this configuration */
    0,          /* configuration name string index */
    USB_CFG_IS_SELF_POWERED,  /* attributes */

    USB_CFG_MAX_BUS_POWER/2,            /* max USB current in 2mA units */
/* interface descriptor follows inline: */
    9,          /* sizeof(usbDescrInterface): length of descriptor in bytes */
    USBDESCR_INTERFACE, /* descriptor type */
    0,          /* index of this interface */
    0,          /* alternate setting for this interface */
    USB_CFG_HAVE_INTRIN_ENDPOINT + USB_CFG_HAVE_INTRIN_ENDPOINT3,   /* endpoints excl 0: number of endpoint descriptors to follow */
    USB_CFG_INTERFACE_CLASS,
    USB_CFG_INTERFACE_SUBCLASS,
    USB_CFG_INTERFACE_PROTOCOL,
    0,          /* string index for interface */


    9,          /* sizeof(usbDescrHID): length of descriptor in bytes */
    USBDESCR_HID,   /* descriptor type: HID */
    0x10, 0x01, /* BCD representation of HID version */
    0x00,       /* target country code */
    0x01,       /* number of HID Report (or other HID class) Descriptor infos to follow */
    0x22,       /* descriptor type: report */
    USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH, 0,  /* total length of report descriptor *///
//#endif


#if USB_CFG_HAVE_INTRIN_ENDPOINT    /* endpoint descriptor for endpoint 1 */
    7,          /* sizeof(usbDescrEndpoint) */
    USBDESCR_ENDPOINT,  /* descriptor type = endpoint */
    0x81,       /* IN endpoint number 1 */
   //0x82,       // bulk IN endpoint number 1
    0x03,       /* attrib: Interrupt endpoint */
   //8, 0,       /* maximum packet size */ // [needed for pc mode ]
    32, 0,       /* maximum packet size */ //  [needed for xbox mode ]
    0x04, /* in ms */

//the output.
    7,          /* sizeof(usbDescrEndpoint) */
    5,  /* descriptor type = endpoint */
    0x02,      /* out endpoint number 2 */
    0x03,       /* attrib: Interrupt endpoint */
    8, 0,       /* maximum packet size */
    0x04, /* in ms */

#endif



#if USB_CFG_HAVE_INTRIN_ENDPOINT3
    7,          // sizeof(usbDescrEndpoint)
    5,  // descriptor type = endpoint
    0x82,       // bulk IN endpoint number 1
    0x03,       // attrib: Interrupt endpoint
    32, 0,       // maximum packet size
    0x04,
 #endif


Here are a few defines.
#define USB_CFG_HAVE_INTRIN_ENDPOINT 1
#define USB_CFG_EP3_NUMBER 2
#define USB_CFG_HAVE_INTRIN_ENDPOINT3 1

I also tried using sendDataUSB3 on the PC with maximum packet size of 8 ( as you said 8 is needed for the PC ) and it two does not work.

I tried setting the end3 to

Code: Select all

#if USB_CFG_HAVE_INTRIN_ENDPOINT3
    7,          // sizeof(usbDescrEndpoint)
    5,  // descriptor type = endpoint
    0x81,       // bulk IN endpoint number 1
    0x03,       // attrib: Interrupt endpoint
    8, 0,       // maximum packet size
    0x04,
 #endif
- and did a usblyzer cap, and nothing sends.

also, I see you use a USB_CFG_INTR_POLL_INTERVAL pf 1, is that not a bit fast?


MackTruman, I'm not sure what exactly you are referring to? Is that directed to me or IvIePhisto . What wont work? The usbSetInterrupt3 function? Who's Code, USB-V ?


____update_____
After looking at usbLyzer some more I saw the out endpoint was in the way and the enpoint 3 was not showing up. So I tried

Code: Select all

#if USB_CFG_HAVE_INTRIN_ENDPOINT    /* endpoint descriptor for endpoint 1 */
    7,          /* sizeof(usbDescrEndpoint) */
    USBDESCR_ENDPOINT,  /* descriptor type = endpoint */
    0x81,       /* IN endpoint number 1 */
   //0x82,       // bulk IN endpoint number 1
    0x03,       /* attrib: Interrupt endpoint */
   8, 0,       /* maximum packet size */ // [needed for pc mode ]
    //32, 0,       /* maximum packet size */ //  [needed for xbox mode ]
    0x04, /* in ms */

//the output.
/*
    7,          // sizeof(usbDescrEndpoint)
    5,  // descriptor type = endpoint
    0x02,      // out endpoint number 2
    0x03,       // attrib: Interrupt endpoint
    8, 0,       // maximum packet size
    0x04, // in ms
*/
#endif



#if USB_CFG_HAVE_INTRIN_ENDPOINT3
    7,          // sizeof(usbDescrEndpoint)
    5,  // descriptor type = endpoint
    0x81,       // bulk IN endpoint number 1
    0x03,       // attrib: Interrupt endpoint
    8, 0,       // maximum packet size
    0x04,
 #endif
Also with 82 on ep3, but still no luck.

Re: usbSetInterrupt3, does it work?

Posted: Sun Aug 22, 2010 5:34 pm
by IvIePhisto
ulao wrote:

Code: Select all

    18 + 7 * USB_CFG_HAVE_INTRIN_ENDPOINT + 7 * USB_CFG_HAVE_INTRIN_ENDPOINT3 + 9, 0,
                /* total length of data returned (including inlined descriptors) */
I think this is wrong, as you got an additional output endpoint, so you got to add 7.
ulao wrote:I also tried using sendDataUSB3 on the PC with maximum packet size of 8 ( as you said 8 is needed for the PC ) and it two does not work.

But you supplied the 20 as packet size? With maximum packet size I meant the value in the descriptor (both in device descriptor and endpoint definitions).
ulao wrote:I tried setting the end3 to

Code: Select all

#if USB_CFG_HAVE_INTRIN_ENDPOINT3
    7,          // sizeof(usbDescrEndpoint)
    5,  // descriptor type = endpoint
    0x81,       // bulk IN endpoint number 1
    0x03,       // attrib: Interrupt endpoint
    8, 0,       // maximum packet size
    0x04,
 #endif
- and did a usblyzer cap, and nothing sends.

This shouldn't work if you use usbSetInterrupt3.
ulao wrote:also, I see you use a USB_CFG_INTR_POLL_INTERVAL pf 1, is that not a bit fast?

We are running with 12 Mhz, so there should be 12000 clock cycles between the polls and we're only reading out pin registers, setting some bits and doing some conditionals - it should be OK, but I've got to admit I never did timing calculations. We never experienced any problems.
ulao wrote:MackTruman, I'm not sure what exactly you are referring to? Is that directed to me or IvIePhisto . What wont work? The usbSetInterrupt3 function? Who's Code, USB-V ?

I think he's a spam bot ;)

I rechecked if this ENDPOINT3 as 2 using sendDataUSB3 is really working for me on PC as I said, and it really does. This is the current status of the SVN repository, feel free to browse it. This is my configuration descriptor:

Code: Select all

PROGMEM const unsigned char usbDescriptorConfigurationXBox[] = {
    9,                      // sizeof(usbDescriptorConfiguration): length of descriptor in bytes
    USBDESCR_CONFIG,             // descriptor type
    32, 0,                  // total length of data returned (including inlined descriptors)
    1,                      // number of interfaces in this configuration
    1,                      // index of this configuration
    0,                      // configuration name string index

   0x80,                   //attributes:Default
   125,                  //power consumption * 2mA
   /*
    (char)USBATTR_BUSPOWER,    // attributes
    USB_CFG_MAX_BUS_POWER/2,   // max USB current in 2mA units
   */
// interface descriptor follows inline:
    9,                       // sizeof(usbDescrInterface): length of descriptor in bytes
    USBDESCR_INTERFACE,         // descriptor type
    0,                      // index of this interface
    0,                     // alternate setting for this interface
    2,                      // endpoints excl 0: number of endpoint descriptors to follow  | ORIGINALLY: 2
    0x58,                  // USB interface class: Unknown
    0x42,                  // USB interface subclass
    0,                     // USB interface protocol
    0,                      // string index for interface
    7,                      // sizeof(usbDescrEndpoint): length of descriptor in bytes
    USBDESCR_ENDPOINT,         // descriptor type = endpoint
    0x82,                  // IN endpoint number 2
    //0x00,                  // attrib: Control endpoint
    //0x01,                  // attrib: Isochronous endpoint
    //0x02,                  // attrib: Bulk endpoint
    0x03,                  // attrib: Interrupt endpoint
    32, 0,                  // maximum packet size, originally 32
    4,                      // interrupt poll interval in ms
    7,                      // sizeof(usbDescrEndpoint): length of descriptor in bytes
    USBDESCR_ENDPOINT,         // descriptor type = endpoint
    0x02,                  // OUT endpoint number 2
    0x03,                  // attrib: Interrupt endpoint
    8, 0,                  // maximum packet size, originally 32
    4                      // interrupt poll interval in ms
};

Edit: is your device recognized or does the OS detect errors?

Re: usbSetInterrupt3, does it work?

Posted: Sun Aug 22, 2010 9:08 pm
by ulao
I think this is wrong, as you got an additional output endpoint, so you got to add 7.
Correct you are, I messed that up, but still no data.

But you supplied the 20 as packet size? With maximum packet size I meant the value in the descriptor (both in device descriptor and endpoint definitions).
Well what I meant is a tried it a few ways. The packet size in the device des, has to be 8, it will not work larger then that with v-usb. But IMO that is ok, I still think it will work.
is your device recognized or does the OS detect errors?
Yeah it recognizes fine just does not send out data.

I tried to set my config up like yours and still dont see data coming out. Still working with it....Based on what I see your code just uses the first in end point for the bulk data. You set EP3 to point to EP1 with a 82 ( bulk ) and it worked? I have * Release 2009-08-22, you have Release 2008-05-13, maybe that is why. I just tried the latest and that got it.

Re: usbSetInterrupt3, does it work?

Posted: Sun Aug 22, 2010 10:08 pm
by IvIePhisto
ulao wrote:
This is my configuration descriptor:
I see you have a default, 1 end in and 1 end out. Maybe I'm counting this wrong.
So you have:

0 - default
1 - in end
2 - out end
and you set your USB_CFG_EP3_NUMBER to 2 which means 1 if you count from 0.
No, in my XBox configuration descriptor I have the default control endpoint (in and out, without declaration) and the endpoint 2 as in and out. The endpoint one I'm only using in PS3 and MAME working mode.
ulao wrote:in my cause I have :
0 - default
1 - out end
2 - in end

So maybe I need to set my USB_CFG_EP3_NUMBER to 3.
No, as I see it you have the default endpoint, one endpoint 1 in, one endpoint 2 out and one endpoint 2 in. Just for clarification, "in" means device-to-host and vice versa for "out" and you can define an endpoint to be in as well as out.
ulao wrote:

Code: Select all

#if USB_CFG_HAVE_INTRIN_ENDPOINT3
    7,          // sizeof(usbDescrEndpoint)
    5,  // descriptor type = endpoint
    0x82,       // bulk IN endpoint number 1
    0x03,       // attrib: Interrupt endpoint
    32, 0,       // maximum packet size
    0x04,
#endif
Didn't spot that earlier, you should change the

Code: Select all

    32, 0,       // maximum packet size
to

Code: Select all

    8, 0,       // maximum packet size
, then it should work with setInterrupt3 on Windows at least.

Re: usbSetInterrupt3, does it work?

Posted: Sun Aug 22, 2010 10:23 pm
by ulao
sorry didnt see your post, I made a lot of edits,, anyways I got it to work. it was a bad version of the code. See my previous post. Now that I have it working let me see if I can nail this down.

------
Got all analogs on the xbox in windows, but not XBOX its self. Not sure what to try next I was hoping this would do it. So about the code. what does this do

if(currentCount > 8 ) currentCount = 8;
^^( dont we want 32 here ? )^^

why keep it at 8 when greater the 8?

------
I think the trick is to get the right maximum packet size for the Xbox.
8 seems to do nothing
0x20 seems to allow some buttons to work but mainly random.
According to what I know the XBOX wants 0x20 for the packet size but we can not set the device descriptor to anything but 8. So my idea was to send 8 packets 4 times ( totaling in the 32 max size ) Then send another.

Something like this ( this does not work )
sendDataUSB3(&XreportBuffer + 0, 4);
sendDataUSB3(&XreportBuffer + 4, 4);
sendDataUSB3(&XreportBuffer + 8, 4);
sendDataUSB3(&XreportBuffer + 12, 4);
sendDataUSB3(&XreportBuffer + 16, 4);
Just sending it all at once is not good enough. sendDataUSB3(XreportBuffer ,20); unless your code is sending in chucks of 32, but I tried playing with that as well with no luck.

Windows wants 0x81 8bytes->8bytes->8bytes-> etc...
Xbox wants 0x82 32bytes->32bytes->32bytes-> etc...

Or at least that is how I understand it.


I wish there was a way yo get v-usb to report 2.0 USB when its not ans set the device descriptor to max of 40. but we can not.

----
Ok this is going to be really hard without knowing whats going on. I found a test controller ISO that I an run on the XBOX ( but now I need to mod it ) This way I can see what bytes are messed up and what not.

----
Hmm, I seem to have gotten windwos to accept 32 byte max packets ans I see the same issue with windows now.
I can not get your code to work with a max size of 32 bytes instead of 8.

Re: usbSetInterrupt3, does it work?

Posted: Mon Aug 23, 2010 10:03 pm
by IvIePhisto
ulao wrote:Got all analogs on the xbox in windows, but not XBOX its self. Not sure what to try next I was hoping this would do it.
As I wrote in the other thread I got this some time ago. This is working if the max packet sizes conforms to the standard by being 8 and the report is splitted into packets of 8 as explained next:
ulao wrote:So about the code. what does this do

if(currentCount > 8 ) currentCount = 8;
^^( dont we want 32 here ? )^^

why keep it at 8 when greater the 8?
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.
ulao wrote:I think the trick is to get the right maximum packet size for the Xbox.
8 seems to do nothing
0x20 seems to allow some buttons to work but mainly random.
Not random in my opinion. I think the XBox does count each packet as the whole report, as the bits set for the analogue axes triggers the functions situated in the beginning of the report (dpad, main buttons).
ulao wrote:Windows wants 0x81 8bytes->8bytes->8bytes-> etc...
For me it works for endpoint no 2 with XBCD, too. But as I see it you defined endpoint 1 as a HID endpoint?
ulao wrote:Xbox wants 0x82 32bytes->32bytes->32bytes-> etc...
Yeah, I think so too, no way around.
ulao wrote:I wish there was a way yo get v-usb to report 2.0 USB when its not ans set the device descriptor to max of 40. but we can not.
Actually it's not USB 2.0 but being a Full (or High) Speed Device, which is defined by pull-down resistors on the data lines. But there the too small buffer comes into play again.
ulao wrote:Hmm, I seem to have gotten windwos to accept 32 byte max packets ans I see the same issue with windows now.
I can not get your code to work with a max size of 32 bytes instead of 8.
Yeah, Windows (7) is detecting a erroneous device for me, if the max packet size is greater than 8.

By the way, I let my MCU count the calls to the following code (the idea coming from UPCB), it is called exactly once:

Code: Select all

       if((rq->bmRequestType & USBRQ_TYPE_MASK) == USBRQ_TYPE_CLASS) {    // class request
         if(rq->bRequest == USBRQ_HID_GET_REPORT) {
            // is called only once in my setup

            usbMsgPtr = data.array;
            //eeprom_write_word((void*)E2END-1, ++debugCount); // DEBUG

            return 20;
         }
      }

And did you see this (I'm pretty sure about the comments without question marks, first number in comment is the value from UPCB):

Code: Select all

   // Vendor Request data
   data.array[20] = 16; // 16 - must be greater than 7, length of this report?
   data.array[21] = 66; // 66 - needed, USB interface subclass?
   data.array[22] = 0;  //  0 - needed, USB interface protocol?
   data.array[23] = 1;  //  1 - must be greater than 0, number of interfaces?
   data.array[24] = 1;  //  1 - needed, configuration index?
   data.array[25] = 2;  //  2 - must be greater than 0, number of endpoints?
   data.array[26] = 8;  // 20 - must be less or equal than max packet size for in endpoint, in max packet size?
   data.array[27] = 6;  //  6 - must be less or equal than max packet size for out endpoint, out max packet size?
It is sent here:

Code: Select all

      if ((rq-> bmRequestType & USBRQ_TYPE_MASK) == USBRQ_TYPE_VENDOR) {
         if(rq->bRequest == 0x06) {
            /*
            receivedData == { 0xc1, 0x06, 0x00, 0x42, 0x00, 0x00, 0x10, 0x00 }
            means (guesses):
            -bmRequestType:
             +direction: device to host
             +type:      vendor
             +recipient: interface
            -request: 0x06
            -wValue:  0, 0x42
            -wIndex:  0, 0
            -wLength: 16
            */
            usbMsgPtr = &data.array[20];

            return 16;
         }
      }

Re: usbSetInterrupt3, does it work?

Posted: Mon Aug 23, 2010 11:07 pm
by ulao
Going to put this thread at rest as its complete and will continue posting on the other thread.
viewtopic.php?f=8&t=4776
I'll no more when I get the controller app running.