Page 2 of 3

Posted: Tue Nov 06, 2007 7:40 pm
by ozel
I also found that the avr stores 16bit numbers in the low byte/high byte format, so you'll have to swap them. I just tested this with the statement below.


yes, I also came to this conclusion. the bytes need the same order as in a 16bit hid report descriptor item (like logical_maximum(1024)).
first low, then high. I think this depends more on the HID protocol spec beeing little endian than on the atmel endianness.

I played with many different descrpitor settings now, some had a physical_min/max together with logical_min/max set to 65535 setting, some only a single report_count and input for X and Y, like you suggested above.
When I set my decriptor like yours (one report_count , 16 bit size and logical_min/max per Usage) it looks like 16bit values are transmitted.

BUT, now the alignment and scaling seems wrong.... :(


I get allways the maximum mouse coordinates 1023 and 767 as X/Y till I send values below 0x03b2...
(edit: note I lowered the maximas in my descriptor by 1 to be 1023 and 767)

When I do:

Code: Select all

//X
reportBuffer[1] = 0xb2; //low byte
reportBuffer[2] = 0x03; //high byte
//Y
reportBuffer[3] = 0xc5;
reportBuffer[4] = 0x02;


Thats the first value where I get 1022/766 and below as actual mouse pointer locations. Can you verify this in your code?
Maybe the main problem is is now just a HID descriptor issue?

And if I make logical_max bigger, the usable range gets even worse = smaller.
edit: It looks like the difference is always 25% on each axis. Strange....

Rukus, thank you very much, so far!
I hope we get this figgured out,
Oli

Posted: Tue Nov 06, 2007 8:53 pm
by Rukus
post your Hid Report Descriptor so I can test it here with what you have. I didn't use physical max and min. perhaps that is where the problem lies?

Posted: Tue Nov 06, 2007 9:11 pm
by Rukus
I just tested it on my end with the HID Report Decriptor I posted and I don't see any problem. I was able to step each axis 1 point at a time down from the (1024 and 768) down to (1022 and 766) and saw now deveation from what I was sending it.

Either you changed something in the Report that I don't have or I'm not understanding the problem.

Posted: Tue Nov 06, 2007 9:25 pm
by ozel
Hm, this sounds good. I have no physical min max at the moment,
I think the only difference to yours is the lower (minus 1) logical_max values.

Code: Select all

char usbHidReportDescriptor[USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH] PROGMEM = {
    0x05, 0x01,                    // USAGE_PAGE (Generic Desktop)
    0x09, 0x02,                    // USAGE (Mouse)
    0xa1, 0x01,                    // COLLECTION (Application)
    0x09, 0x01,                    //   USAGE (Pointer)
    0xa1, 0x00,                    //   COLLECTION (Physical)
    0x05, 0x09,                    //     USAGE_PAGE (Button)
    0x19, 0x01,                    //     USAGE_MINIMUM (Button 1)
    0x29, 0x03,                    //     USAGE_MAXIMUM (Button 3)
    0x15, 0x00,                    //     LOGICAL_MINIMUM (0)
    0x25, 0x01,                    //     LOGICAL_MAXIMUM (1)
    0x95, 0x03,                    //     REPORT_COUNT (3)
    0x75, 0x01,                    //     REPORT_SIZE (1)
    0x81, 0x02,                    //     INPUT (Data,Var,Abs)
    0x95, 0x01,                    //     REPORT_COUNT (1)
    0x75, 0x05,                    //     REPORT_SIZE (5)
    0x81, 0x03,                    //     INPUT (Cnst,Var,Abs)
    0x05, 0x01,                    //     USAGE_PAGE (Generic Desktop)
      //34 till here
      
      //13 below here
    0x09, 0x30,                    //     USAGE (X)
    0x15, 0x00,                    //     LOGICAL_MINIMUM (0)
    0x26, 0xff, 0x03,              //     LOGICAL_MAXIMUM (1023)
    0x75, 0x10,                    //     REPORT_SIZE (16)
    0x95, 0x01,                    //     REPORT_COUNT (1)
    0x81, 0x02,                    //     INPUT (Data,Var,Rel) absolute


      //13 + 2 below here
    0x09, 0x31,                    //     USAGE (Y)
    0x15, 0x00,                    //     LOGICAL_MINIMUM (0)
    0x26, 0xff, 0x02,              //     LOGICAL_MAXIMUM (767)
    0x75, 0x10,                    //     REPORT_SIZE (16)
    0x95, 0x01,                    //     REPORT_COUNT (1)
    0x81, 0x02,                    //     INPUT (Data,Var,Rel) absolute

    0xc0,                          //   END_COLLECTION
    0xc0                           // END_COLLECTION
};


Thanks for testing!

edit:
this is my main() where usbSetInterrupt is called. Maybe here's a problem?
I haven't written it, its from ksz's mouse example. I don't really get what that three cascaded ifs are for....


Code: Select all

int   main(void)
{
uchar   idleCounter = 0;

   wdt_enable(WDTO_2S);
   hardwareInit();
   usbInit();
   sei();
   for(;;){   /* main event loop */
      wdt_reset();
      usbPoll();
        if(TIFR & (1<<TOV0)){   /* 22 ms timer */
            TIFR = 1<<TOV0;
            if(idleRate != 0){
                if(idleCounter > 4){
                    idleCounter -= 5;   /* 22 ms in units of 4 ms */
                }else{
                    idleCounter = idleRate;
                }
            }
        }
        if(buildReport() && usbInterruptIsReady()){
            usbSetInterrupt(reportBuffer, sizeof(reportBuffer));
        }
   }
   return 0;
}

Posted: Tue Nov 06, 2007 9:29 pm
by Rukus
I don't know how you have your array defined, but I have mine setup as a uchar. If somehow you were sending it a number with the high bit set, it would be interepreted as a 2's complement negitive number.

just a thought.


Code: Select all

      uchar AxisBuf[8] ;
      AxisBuf[0]=0xff;
      AxisBuf[1]=0x03;
      AxisBuf[2]=0xff;
      AxisBuf[3]=0x02;

Posted: Tue Nov 06, 2007 9:45 pm
by ozel
No, I use also uchar, otherwise it wouldn't work when doing usbMsgPtr = reportBuffer in usbFunctionSetup() because usbMsgPtr is uchar by AVR-USB's internals.

Does it also work with my descriptor above on your setup, that you can step trough all pixels? Is my main() above ok?

Posted: Tue Nov 06, 2007 9:58 pm
by Rukus
ozel wrote:No, I use also uchar, otherwise it wouldn't work when doing usbMsgPtr = reportBuffer in usbFunctionSetup() because usbMsgPtr is uchar by AVR-USB's internals.

Does it also work with my descriptor above on your setup, that you can step trough all pixels? Is my main() above ok?


I cant test it because I don't have your message builder routine and I don't know what you are sending to the setinterupt. If I don't have all of the data being sent properly the link will stall on the host side.

My guess from looking at what you posted, it has something to do with the buttons. If you don't have the bit alignment right as far as 8 total bits being used just ahead of these axis definitions, my guess is it will muck with the data for the X and Y axis. The HID depends on things being packed into the bits end to end. and if there is a gap...it'll mess things up.

try first by removing the buttons. If it works ok then...define 8 total buttons so things get lined up right. then lets see what happens

Posted: Tue Nov 06, 2007 10:06 pm
by Rukus
it may also have something to do with the way you are declaring the buttons.

I'd get rid of the

Code: Select all

   0x95, 0x01,                    //     REPORT_COUNT (1) 
    0x75, 0x05,                    //     REPORT_SIZE (5)
    0x81, 0x03,                    //     INPUT (Cnst,Var,Abs)
    0x05, 0x01,                    //     USAGE_PAGE (Generic Desktop)


and define buttons 1 - 8 with a size of 1 and number of 8.

I'm still new at this stuff too. I'm not quite sure but it has to do with this stuff.

edit: Also i'm not sure how the constant declaration would work with a button.

edit: you also have a relitive declaration statement for the axis. I'm guessing you want absolute instead.

Posted: Tue Nov 06, 2007 10:38 pm
by Rukus
I was just using the Hid Descriptor tool and I called up a mouse and noticed it looked alot like your declarations except for the fact that
the X and Y position is only 8 bit.

If you are creating a mouse, you would want relitive on the axises, however i wouldn't expect you would need a 16 bit number. The reletive statement means this is how much it has changed since last scan. In your case it would mean you had a full screen with or height change in one scan?

anyway.....I hope you figure it out. I'm not quite sure what you are trying to do, so I cant be much help. you mentioned a touch screen....to me that might mean absolute?

Posted: Tue Nov 06, 2007 10:56 pm
by ozel
Rukus wrote:it may also have something to do with the way you are declaring the buttons.

I'd get rid of the

Code: Select all

   0x95, 0x01,                    //     REPORT_COUNT (1) 
    0x75, 0x05,                    //     REPORT_SIZE (5)
    0x81, 0x03,                    //     INPUT (Cnst,Var,Abs)
    0x05, 0x01,                    //     USAGE_PAGE (Generic Desktop)


and define buttons 1 - 8 with a size of 1 and number of 8.

[/code]

(...)

edit: Also i'm not sure how the constant declaration would work with a button.


hm, but I know this descriptor works perfectly for a relative mouse setting. Others have used it succesfull (http://szczuka.eu/avr/irmouse.php). And it worked also on my host, sending the right buttons and relative x/y values. The 5 bits padding is ok, also declaring it as constant.

edit: you also have a relitive declaration statement for the axis. I'm guessing you want absolute instead.


Where? I can't see it. I have 0x81 set to 0x02 which only sets the variable bit and leaves the relative bit untouched.

I'm sorry that I caused confusion with only releasing bits of my code, I thought it would be easier to keep track of it, for others. Its all really basic on my side, here is everything:

Code: Select all

/* Name: main.c
 * Project: USB HID Mouse (derived from OBDEV's HID test)
 * Author: Christian Starkjohann / Krzysiek Szczuka
 * Creation Date: 2007-01-08
 * Tabsize: 4
 * Copyright: (c) 2006 by Christian Starkjohann
 *                2007 by Krzysiek Szczuka
 * License: Proprietary, free under certain conditions. See Documentation.
 * This Revision: $Id: main.c,v 1.3 2007/01/09 20:47:24 ksz Exp $
 *
 * CHANGED:
 * - reset/config button on ATouch acts as a coordinate send button for
 *   testing
 * - updated to newest (as of 03.11.07) AVR-USB driver (usbdrv directory)
 * Oliver Keller, 6.11.07
 *
 */


#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <avr/wdt.h>
#include <util/delay.h>


#include "usbdrv.h"
#include "binary.h"

// LED on PD6
#define LED  6

// we have one test button
#define BUTTONPIN PINB   
#define BUTTON  2   

static void hardwareInit(void)
{
uchar   i, j;   
  DDRD  = (_BV(LED) | USBMASK);     //all pins input exept LED and USB pins
  PORTD = 0;    //pullups off, outputs low (-> USB reset)

  /* We fake an USB disconnect by pulling D+ and D- to 0 during reset. This is
    * necessary if we had a watchdog reset or brownout reset to notify the host
    * that it should re-enumerate the device. Otherwise the host's and device's
    * concept of the device-ID would be out of sync.
    */

   DDRC  = 0;       //all pins input
   PORTC = 0;      //pullups off, all pins tri-stated, high-Z

   DDRB  = 0;       //all pins input
   PORTB = 0;      //pullups off, all pins tri-stated, high-Z
 
   j = 0;
   while(--j){     /* USB Reset by device only required on Watchdog Reset */
      i = 0;
      while(--i); /* delay >10ms for USB reset */
   }
    DDRD &= ~USBMASK;    /* remove USB reset condition */
    /* configure timer 0 for a rate of 12M/(1024 * 256) = 45.78 Hz (~22ms) */
    TCCR0 = 5;      /* timer 0 prescaler: 1024 */
}



/* ------------------------------------------------------------------------- */
/* ----------------------------- USB interface ----------------------------- */
/* ------------------------------------------------------------------------- */


static uchar  reportBuffer[5];    /* buffer for HID reports */
//static uchar  idleRate;           /* in 4 ms units */

// absolute mouse HID descriptor
char usbHidReportDescriptor[USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH] PROGMEM = {
    0x05, 0x01,                    // USAGE_PAGE (Generic Desktop)
    0x09, 0x02,                    // USAGE (Mouse)
    0xa1, 0x01,                    // COLLECTION (Application)
    0x09, 0x01,                    //   USAGE (Pointer)
    0xa1, 0x00,                    //   COLLECTION (Physical)
    0x05, 0x09,                    //     USAGE_PAGE (Button)
    0x19, 0x01,                    //     USAGE_MINIMUM (Button 1)
    0x29, 0x03,                    //     USAGE_MAXIMUM (Button 3)
    0x15, 0x00,                    //     LOGICAL_MINIMUM (0)
    0x25, 0x01,                    //     LOGICAL_MAXIMUM (1)
    0x95, 0x03,                    //     REPORT_COUNT (3)
    0x75, 0x01,                    //     REPORT_SIZE (1)
    0x81, 0x02,                    //     INPUT (Data,Var,Abs)
    0x75, 0x01,                    //     REPORT_SIZE (1)
    0x95, 0x05,                    //     REPORT_COUNT (5)
    0x81, 0x03,                    //     INPUT (Cnst,Var,Abs)
    0x05, 0x01,                    //     USAGE_PAGE (Generic Desktop)
      //34 till here
      
      //13 below here
    0x09, 0x30,                    //     USAGE (X)
    0x15, 0x00,                           //     LOGICAL_MINIMUM (0)
    0x26, 0xff, 0x03,              //     LOGICAL_MAXIMUM (1023)
//      0x36, 0x00,                    //     PHYSICAL_MINIMUM (0)
//      0x45, 0xff, 0xff,                      //     PHYSICAL_MAXIMUM (1023)
    0x75, 0x10,                    //     REPORT_SIZE (16)
    0x95, 0x01,                    //     REPORT_COUNT (1)
    0x81, 0x02,                    //     INPUT (Data,Var,Rel) absolute


      //13 + 2 below here
      0x09, 0x31,                    //     USAGE (Y)
    0x15, 0x00,                           //     LOGICAL_MINIMUM (0)
    0x26, 0xff, 0x02,              //     LOGICAL_MAXIMUM (767)
    0x75, 0x10,                    //     REPORT_SIZE (16)
    0x95, 0x01,                    //     REPORT_COUNT (1)
    0x81, 0x02,                    //     INPUT (Data,Var,Rel) absolute

    0xc0,                          //   END_COLLECTION
    0xc0                           // END_COLLECTION
};

static char buildReport(void)
{
   // retval 1 means, that something changed and we must send report
   char retval = 0;
   
   // check test button
   if ( (BUTTONPIN & _BV(BUTTON)) == !_BV(BUTTON) ) {   
      // set X
     reportBuffer[1] = 0xb2; //low byte
     reportBuffer[2] = 0x03; //high byte
    // gets my the coordinate 1022 on my host, while it should be only 946
    // all higher values than 0x03b2 result in the logical_maximum value of 1023

    // set Y
     reportBuffer[3] = 0xc5;
     reportBuffer[4] = 0x02;
      //gets me the coordinate 766 on my host, while it should be only 709
    //all higher values than 0x02c5 result in the logical_maximum value of 767
   
      retval = 1;
    }
   return retval;
}

uchar   usbFunctionSetup(uchar data[8])
{
usbRequest_t    *rq = (void *)data;

    usbMsgPtr = reportBuffer;
    if((rq->bmRequestType & USBRQ_TYPE_MASK) == USBRQ_TYPE_CLASS){    /* class request type */
        if(rq->bRequest == USBRQ_HID_GET_REPORT){  /* wValue: ReportType (highbyte), ReportID (lowbyte) */
            /* we only have one report type, so don't look at wValue */
            //buildReport();
            return sizeof(reportBuffer);
        }

            /* ???
            else if(rq->bRequest == USBRQ_HID_GET_IDLE){
            usbMsgPtr = &idleRate;
            return 1;
        }else if(rq->bRequest == USBRQ_HID_SET_IDLE){
            idleRate = rq->wValue.bytes[1];
        }*/

    }else{
        /* no vendor specific requests implemented */
    }
   return 0;
}

/* ------------------------------------------------------------------------- */

int   main(void)
{
//uchar   idleCounter = 0;

   wdt_enable(WDTO_2S);
   hardwareInit();
   usbInit();
   sei();
   for(;;){   /* main event loop */
      wdt_reset();
      usbPoll();
      
/*  don't know what this was supposed for...
      if(TIFR & (1<<TOV0)){   // 22 ms timer
            TIFR = 1<<TOV0;
            if(idleRate != 0){
                if(idleCounter > 4){
                    idleCounter -= 5;   // 22 ms in units of 4 ms
                }else{
                    idleCounter = idleRate;
                }
            }
        }
*/
        if(buildReport() && usbInterruptIsReady()){
            usbSetInterrupt(reportBuffer, sizeof(reportBuffer));
        }
   }
   return 0;
}

/* ------------------------------------------------------------------------- */


so you see there is no real difference to your test code, I guess. If you increase your AxisBuf by one and skip the "0" entry when filling it with x/y data, you have the same message builder routine like me, right?

My code just sends a coordinate pair for testing, when a button is hit.
Later I will meassure the coordinates as resistance values form a touchscreen panel and send them instead. :)
For now I don't generate left/right mouse button events, cause I know they are reported correct. Thats why I don't set reportBuffer[0] anywhere.

I would be really happy if you could test this code/descriptor on your host.

Thanks again,
Oli

Posted: Tue Nov 06, 2007 11:35 pm
by Rukus
Perhaps later tonight. I'm trying to get a couple of programs meshed together. I just re-installed the newest version of the avr-usb driver. The program that I found on the web needed alot of work to get it to run with the new version. Not the fault of christian, its just there were several changes the program writer felt he needed to add in the usb.c program and it drove the compiler nuts till I found all the bugs.

Don't get disheartened with this. This stuff is really tough. I'm just a noob at this. I think i've just about used up my allowance of flash memory writes for this new atmega8 in only a week :lol:

in the begining trying to get the usb to do what I wanted it was like

burn program
reset
beep beep beep
damit
re-write some code
burn program
reset
beep beep beep etc.
double damit :lol:

Posted: Fri Nov 09, 2007 3:44 am
by Rukus
Ozel, did you get it working?

Posted: Fri Nov 09, 2007 4:37 am
by ozel
hey,

no its really strange. I started sending just 8bit, as the touchscreen sensing part is my first goal. I think there is serious knowledge missing, on how all the hid parameters get interpreted. For example it doesn't make much difference at all (on my host), when I change the logical maximums!
As I will use my controller on a linux driven device later, I thought, I won't care to much on how it performs on my mac. Maybe the absolute mouse behaviour is later completly different in xorg's window system...

But I'd be interetested in your test code, where you said, you could step in 16 bit through all the axis values. Could you post it? I don't care if its no mouse but a joystick profile. I think it could be a good starting point to track the difference to my absolute mouse profile code.

Good night,
Oli
p.s. I know the reset cycles well ;) just switched off veryfing the flash on uploads, so it gets one second faster... anyone ever used JTAG for debugging? It might save some hours... and not to forget a USB HID analyzer of course ;)

Posted: Fri Nov 09, 2007 10:05 am
by Grendel
Here's a working report descriptor for a "live" joystick for reference, 4 axis -- X (10bit), Y (10bit), Rz (9bit, handle twist), throttle (10bit, slider) -- 8 buttons (4 on the stick, 4 on the base), and a POV hat switch.

Code: Select all

#define CFG_HID_REPORT_DESC_SZ_3DP 102

PROGMEM char
    usbHidReportDesc3DP[] =
    {
   0x05,0x01,      // USAGE_PAGE (Generic Desktop)
   0x09,0x04,      // USAGE (Joystick)
   0xA1,0x01,      // COLLECTION (Application)
   0x09,0x01,      //   USAGE (Pointer)
   0xA1,0x00,      //   COLLECTION (Physical)
   0x95,0x02,      //     REPORT_COUNT (2)
   0x75,0x0A,      //     REPORT_SIZE (10)
   0x16,0x00,0xFE,      //     LOGICAL_MINIMUM (-512)
   0x26,0xFF,0x01,      //     LOGICAL_MAXIMUM (511)
   0x35,0x00,      //     PHYSICAL_MINIMUM (0)
   0x46,0xFF,0x03,      //     PHYSICAL_MAXIMUM (1023)
   0xA4,         //     PUSH
   0x09,0x30,      //     USAGE (X)
   0x09,0x31,      //     USAGE (Y)
   0x81,0x02,      //     INPUT (Data,Var,Abs)             20b X/Y
   0x95,0x01,      //     REPORT_COUNT (1)
   0x75,0x09,      //     REPORT_SIZE (9)
   0x16,0x00,0xFF,      //     LOGICAL_MINIMUM (-256)
   0x26,0xFF,0x00,      //     LOGICAL_MAXIMUM (255)
   0x45,0x2E,      //     PHYSICAL_MAXIMUM (46)
   0x65,0x14,      //     UNIT (Eng Rot:Angular Pos)
   0x09,0x35,      //     USAGE (Rz)
   0x81,0x02,      //     INPUT (Data,Var,Abs)              9b Rz
   0x95,0x01,      //     REPORT_COUNT (1)
   0x75,0x04,      //     REPORT_SIZE (4)
   0x15,0x00,      //     LOGICAL_MINIMUM (0)
   0x25,0x07,      //     LOGICAL_MAXIMUM (7)
   0x46,0x3B,0x01,      //     PHYSICAL_MAXIMUM (315)
   0x09,0x39,      //     USAGE (Hat switch)
   0x81,0x42,      //     INPUT (Data,Var,Abs,Null)         4b Hat
   0x95,0x04,      //     REPORT_COUNT (4)
   0x75,0x01,      //     REPORT_SIZE (1)
   0x25,0x01,      //     LOGICAL_MAXIMUM (1)
   0x45,0x01,      //     PHYSICAL_MAXIMUM (1)
   0x65,0x00,      //     UNIT (None)
   0x05,0x09,      //     USAGE_PAGE (Button)
   0x19,0x01,      //     USAGE_MINIMUM (Button 1)
   0x29,0x04,      //     USAGE_MAXIMUM (Button 4)
   0x81,0x02,      //     INPUT (Data,Var,Abs)              4b B1-4
   0xC0,         //   END_COLLECTION
   0x19,0x05,      //   USAGE_MINIMUM (Button 5)
   0x29,0x08,      //   USAGE_MAXIMUM (Button 8)
   0x81,0x02,      //   INPUT (Data,Var,Abs)                4b B5-8
   0xB4,         //   POP
   0x95,0x01,      //   REPORT_COUNT (1)
   0x09,0x36,      //   USAGE (Slider)
   0x81,0x02,      //   INPUT (Data,Var,Abs)               10b Throttle
   0x75,0x05,      //   REPORT_SIZE (5)
   0x81,0x01,      //   INPUT (Cnst,Ary,Abs)                5b Fill
   0xC0         // END_COLLECTION                       56b -> 7bytes
    } ;


The report data array is defined as:

Code: Select all

uint8_t
    sw_report[7] ;                              // USB report data

//      USB report data structure
//      =========================
//
//      -------0 -------1 -------2 -------3 -------4 -------5 -------6
//      XXXXXXXX YYYYYYXX RRRRYYYY HHHRRRRR BBBBBBBH TTTTTTTB 00000TTT
//      76543210 54321098 32109876 21087654 76543213 65432108      987
//
//      R = Rz, H = POV hat, B = button, T = throttle

Posted: Tue Nov 13, 2007 6:12 pm
by sprhawk
what's this descriptor wrong?

Code: Select all

char usbHidReportDescriptor[41] = {
   0x05, 0x01,                    // USAGE_PAGE (Generic Desktop)
   0x09, 0x04,                    // USAGE (Joystick)
   0xa1, 0x01,                    // COLLECTION (Application)
   0x09, 0x01,                    //   USAGE (Pointer)
   0xa1, 0x00,                    //   COLLECTION (Physical)
   0x09, 0x30,                    //     USAGE (X)
   0x15, 0x80,                    //     LOGICAL_MINIMUM (-128)
    0x25, 0x7f,                    //     LOGICAL_MAXIMUM (127)
    0x95, 0x01,                    //     REPORT_COUNT (1)
    0x75, 0x08,                    //     REPORT_SIZE (8)   
   0x81, 0x02,                    //     INPUT (Data,Var,Abs)
   0xc0,                          //   END_COLLECTION
    0x05, 0x02,                    // USAGE_PAGE (Simulation Controls)
    0xa1, 0x00,                    //   COLLECTION (Physical)
   0x09, 0xba,                    //     USAGE (Rudder)   
   0x15, 0x80,                    //     LOGICAL_MINIMUM (-128)
    0x25, 0x7f,                    //     LOGICAL_MAXIMUM (127)
    0x75, 0x08,                    //     REPORT_SIZE (8)
    0x95, 0x01,                    //     REPORT_COUNT (1)
    0x81, 0x02,                    //     INPUT (Data,Var,Abs)
    0xc0,                          //   END_COLLECTION
    0xc0                           // END_COLLECTION
};


it causes an exclaimination on the USB HID device in Device Manager.
I tried the separate the two usage(page) are both ok, but the combination is error.

I mean these are OK:
1.

Code: Select all

char usbHidReportDescriptor[24] = {
   0x05, 0x01,                    // USAGE_PAGE (Generic Desktop)
   0x09, 0x04,                    // USAGE (Joystick)
   0xa1, 0x01,                    // COLLECTION (Application)
    0x05, 0x02,                    //    USAGE_PAGE (Simulation Controls)
    0xa1, 0x00,                    //   COLLECTION (Physical)
   0x09, 0xba,                    //     USAGE (Rudder)   
   0x15, 0x80,                    //     LOGICAL_MINIMUM (-128)
    0x25, 0x7f,                    //     LOGICAL_MAXIMUM (127)
    0x75, 0x08,                    //     REPORT_SIZE (8)
    0x95, 0x01,                    //     REPORT_COUNT (1)
    0x81, 0x02,                    //     INPUT (Data,Var,Abs)
    0xc0,                          //   END_COLLECTION
    0xc0                           // END_COLLECTION
};

and

Code: Select all

char usbHidReportDescriptor[24] = {
   0x05, 0x01,                    // USAGE_PAGE (Generic Desktop)
   0x09, 0x04,                    // USAGE (Joystick)
   0xa1, 0x01,                    // COLLECTION (Application)
   0x09, 0x01,                    //   USAGE (Pointer)
   0xa1, 0x00,                    //   COLLECTION (Physical)
   0x09, 0x32,                    //     USAGE (X)
   0x15, 0x80,                    //     LOGICAL_MINIMUM (-128)
    0x25, 0x7f,                    //     LOGICAL_MAXIMUM (127)
    0x95, 0x01,                    //     REPORT_COUNT (1)
    0x75, 0x08,                    //     REPORT_SIZE (8)   
   0x81, 0x02,                    //     INPUT (Data,Var,Abs)
   0xc0,                          //   END_COLLECTION
    0xc0                           // END_COLLECTION
};


I give both of them two bytes data