SOLVED: How to send mulitple reports over one interrupt endp

General discussions about V-USB, our firmware-only implementation of a low speed USB device on Atmel's AVR microcontrollers
Post Reply
frampy
Posts: 2
Joined: Tue Aug 27, 2013 10:51 am

SOLVED: How to send mulitple reports over one interrupt endp

Post by frampy » Tue Aug 27, 2013 11:07 am

I've been building a USB joystick controller for use in an arcade machine using V-USB. I've setup my report descriptor to contain two different reports using the REPORT_ID field (one for each player on tha machine).

I can send a report for each of the players individually, like so.

Code: Select all

if (TCNT0 > 47)  //47 == 4ms approx
{
    if (usbInterruptIsReady())
    {
        // this works fine, but only send a report for player 1
        buildReport(&gamepads[0], reportBuffer);
        usbSetInterrupt(reportBuffer, REPORT_SIZE);
    }
}


But I cannot send both reports squentially, I found some example code at http://www.raphnet.net/electronique/2ne ... dex_en.php which I've used to template this, but it doesn't work for me. Reference the following code sample, after usbSetInterrupt() is called, the code enters a loop waiting for the buffer to clear so we can set another interrupt, but the code gets stuck in this loop and never returns.

Someone help please! Programmer in peril.

Code: Select all

if (TCNT0 > 47) //47 == 4ms approx
{
    TCNT0 = 0;
    for (gp = 0; gp < NUM_GAMEPADS; gp++)
    {
        buildReport(&gamepads[gp], reportBuffer);
        if (usbInterruptIsReady())
        {
            usbSetInterrupt(reportBuffer, REPORT_SIZE);
            while (!usbInterruptIsReady())
            {
                // code hangs in this loop
                usbPoll();
                wdt_reset();

                // when uncommented, this toggles furiously!
                //toggle_pin();
            }
        }
    }
    // never see this toggled
    toggle_pin();
}



Thanks for your time

--Mike
Last edited by frampy on Wed Aug 28, 2013 3:10 am, edited 1 time in total.

frampy
Posts: 2
Joined: Tue Aug 27, 2013 10:51 am

Re: How to send mulitple reports over one interrupt endpoint

Post by frampy » Wed Aug 28, 2013 3:09 am

I figured out why the code gets stuck in the loop waiting for usbInterruptIsReady() to return true.

The OS I'm using (Linux) won't poll the USB device unless there is a program actually using the device. In my case I'm running the following command to poll the device.

Code: Select all

jstest --event /dev/input/js0

Which polls the device just fine.

I was also able to reduce USB_CFG_INTR_POLL_INTERVAL to 2ms (not tested on windows).

I managed to get the two reports sending successfully using the following code. - this is mostly inspired by code found on raphnet.net

Code: Select all

    uint8_t must_report = 0;
    while(1) {

        wdt_reset();
        usbPoll(); //this must be called approx every 50ms

        pollButtons(&must_report);

        if (must_report) {
            for (gp = 0; gp < NUM_GAMEPADS; gp++) {
                if (must_report & (1 << gp) == 0)
                    continue;

                if (usbInterruptIsReady()) {
                    buildReport(&gamepads[gp], reportBuffer);
                    usbSetInterrupt(reportBuffer, REPORT_SIZE);
                    must_report &= ~(1 << gp);

                    while (!usbInterruptIsReady()) {
                        usbPoll();
                        wdt_reset();
                        pollButtons(&must_report);
                    }
                }
            }
        }
    }


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

Re: SOLVED: How to send mulitple reports over one interrupt

Post by ulao » Wed Aug 28, 2013 9:26 pm

its been understood for a long time that Linux will not work with mutiple descriptor reports like that, are you saying you over came that?

like this for example.
viewtopic.php?f=8&t=2926&p=9925&hilit=multi+linux#p9925

Post Reply